stdinにタイムスタンプを付加するUnixユーティリティはありますか?


168

私はこれでPythonで簡単な短いスクリプトを作成しましたが、テキストをフィードして、各行の前にテキストを追加できるユーティリティがあるかどうか疑問に思っていました。私の特定のケースでは、タイムスタンプです。理想的には、使用は次のようになります。

cat somefile.txt | prepend-timestamp

(sedと答える前に、私はこれを試しました:

cat somefile.txt | sed "s/^/`date`/"

ただし、これはsedの実行時にdateコマンドを1回だけ評価するため、同じタイムスタンプが各行に誤って付加されます。)


cat somefile.txt「誤解を招く」ビット?私はそれが「一度に」起こり、単一のタイムスタンプを持つことを期待します。これはより良いテストプログラムではないでしょう(echo a; sleep 1; echo b; sleep 3; echo c; sleep 2)か?
Ciro Santilli郝海东冠状病六四事件法轮功

回答:


185

使用してみてくださいawk

<command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }'

<command>ラインバッファリングされた出力を生成することを確認する必要がある場合があります。タイムスタンプがawk追加されるのは、行の終わりが入力パイプに表示された時間です。

awkがエラーを表示する場合は、gawk代わりに試してください。


31
私のシステムでは、「awk」自体がバッファリングされていました。(これはログファイルにとって問題になる可能性があります)。私はこれを使ってこれを修正しました:awk '{print strftime( "%Y-%m-%dT%H:%M:%S")、$ 0; fflush(); } '
user47741

19
strftime()はGNU awk拡張機能のように見えるため、たとえばMac OSを使用している場合は、awkではなくgawkを使用してください。
Joe Shaw

それは私がどれほど強力なバッシュであるか私を驚かせることを止めません。私は、この複雑なタスクにそのような簡単な解決策があるとは思いませんでした。
リキュール

2
OS Xユーザーのgawk場合、の代わりにそれをインストールして使用する必要がありますawk。MacPortsを使用している場合:sudo port install gawk
Matt Williamson

5
@teh_senaus私の知る限り、awkstrftime()ミリ秒の精度はありません。ただし、dateコマンドは使用できます。基本的には、ナノ秒を3文字にトリミングするだけです。次のようになりますCOMMAND | while read -r line; do echo "$(date '+%Y-%m-%d %T.%3N') $line"; done。%H:%M:%Sは%Tで省略できることに注意してください。あなたはまだ使用したい場合はawk、いくつかの理由で、次の操作を行うことができます:COMMAND | awk '{ "date +%Y-%m-%d\\ %T.%3N" | getline timestamp; print timestamp, $0; fflush(); }'
シックス・

190

tsmoreutilsからは、入力するすべての入力行にタイムスタンプを付加します。strftimeを使用してフォーマットすることもできます。

$ echo 'foo bar baz' | ts
Mar 21 18:07:28 foo bar baz
$ echo 'blah blah blah' | ts '%F %T'
2012-03-21 18:07:30 blah blah blah
$ 

それをインストールするには:

sudo apt-get install moreutils

2
stderrを同時にキャプチャしてスタンプする:bad command 2>&1 | ts結果はJan 29 19:58:31 -bash: bad: command not found
rymo 2014年

時間形式を使いたい2014 Mar 21 18:07:28。どうすれば入手できますか?
becko 14

@becko- マニュアルページによると、たとえば、strftimeフォーマット文字列を引数として指定します[.. command ..] | ts '%Y %b %d %T'
Toby Speight 2015年

2
OS Xの場合brew install moreutils。UTCを出力するには、TZをローカルに設定できます。例ls -l |TZ=UTC ts '%Y-%m-%dT%H:%M:%SZ'
karmakaze

1
@Dorianこれは、rubyが出力をバッファリングしているためです。スリープする前にバッファをフラッシュすると、十分機能します。ruby -e "puts 1; STDOUT.flush; sleep 1; puts 2; STDOUT.flush; sleep 2; puts 3" | ts '%F %T'
umläuteJan

45

annotate、そのリンクを介して、またはannotate-outputDebian devscriptsパッケージと同様に利用できます。

$ echo -e "a\nb\nc" > lines
$ annotate-output cat lines
17:00:47 I: Started cat lines
17:00:47 O: a
17:00:47 O: b
17:00:47 O: c
17:00:47 I: Finished with exitcode 0

1
これは優れたソリューションですが、パイプ出力またはサブシェル出力では機能しません。引数として指定したプログラムまたはスクリプトの出力のみを再フォーマットします。
slm 2014

1
annotate-outputはうまく機能し、使いやすいですが、本当に遅いです。
ポールブランナン

31

与えられた答えを可能な限り単純なものに蒸留します:

unbuffer $COMMAND | ts

Ubuntuでは、expect-devおよびmoreutilsパッケージに含まれています。

sudo apt-get install expect-dev moreutils

1
それexpectはそうexpect-devではありませんが、後者は前者を引き込むので、これは機能します。(Ubuntu 14.10、バイナリが
いつか

Ubuntu 14.04 LTSの場合、それはまだ残っていますexpect-dev
ウィレム

2
経過時間をミリ秒の精度で取得したい場合は、unbuffer $COMMAND | ts -s %.s-s経過時間および%.s秒単位の時間の場合は小数部を使用)
Greg Witczak

24

これはどう?

cat somefile.txt | perl -pne 'print scalar(localtime()), " ";'

ライブタイムスタンプを取得したいという希望から判断すると、ログファイルなどでライブ更新を実行したい場合は、多分

tail -f /path/to/log | perl -pne 'print scalar(localtime()), " ";' > /path/to/log-with-timestamps

4
このperlの例は、ubuntuデプロイメントでユーザーとして作業しているときに特に役立ちました。これは、明らかに「gawk」ではなく「mawk」を使用しており、strftime関数がありません。ありがとう!
opello 2010

4
これを+1することは、デフォルトのUbuntuインストールで便利です。私が使用tail -f /path/to/log | perl -pne 'use POSIX qw(strftime); print strftime "%Y-%m-%dT%H:%M:%SZ ", gmtime();'死霊のかぼちゃ1簡単なバージョンの利回りの代わりにISO8601 / RFC3339形式の日付を取得します。
natevw 2013年

1
到着時にタイムスタンプ付きのログ出力を確認できるようにしたい場合BEGIN { $|++; }は、Perlに出力を各行でフラッシュさせるために、printステートメントの前に追加すると役立つ場合があります。

2
perlスクリプトをさらに短くして、だけにすることができls | perl -pne 'print localtime." "'ます。文字列の連結が原因でスカラー変換が行われます。
rahul 2015年

-p-nオプションの両方を使用するのはなぜですか?のように思える-nあなたが指定した場合に冗長です-p
Davor Cubranic


18

キーロンの答えは今のところ最高です。最初のプログラムがバッファリングしているために問題が発生した場合は、unbufferプログラムを使用できます。

unbuffer <command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }'

ほとんどのLinuxシステムにデフォルトでインストールされます。自分でビルドする必要がある場合は、expectパッケージの一部です

http://expect.nist.gov


'unbuffer'が呼び出されたプログラムの戻り結果を隠す場合があることに
気づいたことに注意してください。Jenkinsなど

10

read(1)コマンドを使用して、標準入力から一度に1行を読み取り、date(1)を使用して選択した形式で日付を前に付けて行を出力します。

$ cat timestamp
#!/bin/sh
while read line
do
  echo `date` $line
done
$ cat somefile.txt | ./timestamp

2
行ごとに新しいプロセスをforkするので少し重いですが、動作します!
ジョーショー

3

私はUnixの人ではありませんが、あなたは使うことができると思います

gawk '{print strftime("%d/%m/%y",systime()) $0 }' < somefile.txt

3
#! /bin/sh
unbuffer "$@" | perl -e '
use Time::HiRes (gettimeofday);
while(<>) {
        ($s,$ms) = gettimeofday();
        print $s . "." . $ms . " " . $_;
}'

2

これが私のawkソリューションです(MKSツールがC:\ binディレクトリにインストールされているWindows / XPシステムから)。これは、現在の日付と時刻をmm / dd hh:mmの形式で、各行が読み取られるときにシステムからタイムスタンプをフェッチした各行の先頭に追加するように設計されています。もちろん、BEGINパターンを使用してタイムスタンプを1回フェッチし、そのタイムスタンプを各レコードに追加することもできます(すべて同じです)。これは、ログメッセージが生成されたときのタイムスタンプでstdoutに生成されているログファイルにタグを付けるために行いました。

/"pattern"/ "C\:\\\\bin\\\\date '+%m/%d %R'" | getline timestamp;
print timestamp, $0;

ここで、「パターン」は、入力行で照合する文字列または正規表現(引用符なし)であり、すべての入力行を照合する場合はオプションです。

これはLinux / UNIXシステムでも機能するはずです。C\:\\ bin \\を削除して、次の行を残してください。

             "date '+%m/%d %R'" | getline timestamp;

もちろん、これは、コマンド「date」が特定のパス情報なしで標準のLinux / UNIXの日付表示/設定コマンドにアクセスできることを前提としています(つまり、環境のPATH変数が正しく構成されています)。


OS XIでは、dateコマンドの前にスペースが必要でした。悲しいことに、それは各行のコマンドを再評価していないようです。他の人が提案したように、私はtail -fにタイムスタンプを追加しようとしています。
Mark Bennett

2

上記のいくつかの答えミキシングnatevwとフランク・Chのを。アイグラー。

ミリ秒で、date毎回外部コマンドを呼び出すよりもパフォーマンスがよく、ほとんどのサーバーでperlを見つけることができます。

tail -f log | perl -pne '
  use Time::HiRes (gettimeofday);
  use POSIX qw(strftime);
  ($s,$ms) = gettimeofday();
  print strftime "%Y-%m-%dT%H:%M:%S+$ms ", gmtime($s);
  '

フラッシュとループで読み取る代替バージョン:

tail -f log | perl -pne '
  use Time::HiRes (gettimeofday); use POSIX qw(strftime);
  $|=1;
  while(<>) {
    ($s,$ms) = gettimeofday();
    print strftime "%Y-%m-%dT%H:%M:%S+$ms $_", gmtime($s);
  }'

1
上記の2つの欠点:1. $ msは整列されず、ゼロが埋め込まれません。2.ログ内の%コードはすべて破損します。代わりに、印刷ラインのかくして、私が使用される: printf "%s+%06d %s", (strftime "%Y-%m-%dT%H:%M:%S", gmtime($s)), $ms, $_;
サイモンピックアップ

2
$ cat somefile.txt | sed "s/^/`date`/"

これを行うことができます(gnu / sedを使用):

$ some-command | sed "x;s/.*/date +%T/e;G;s/\n/ /g"

例:

$ { echo 'line1'; sleep 2; echo 'line2'; } | sed "x;s/.*/date +%T/e;G;s/\n/ /g"
20:24:22 line1
20:24:24 line2

もちろん、プログラムの日付の他のオプションを使用できます。date +%T必要なものに置き換えるだけです。


1

caerwynの回答はサブルーチンとして実行できます。これにより、行ごとの新しいプロセスが妨げられます。

timestamp(){
   while read line
      do
         echo `date` $line
      done
}

echo testing 123 |timestamp

3
どのようにしてdateすべての行でスポーンされるのを防ぎますか?
Gyom 2013年

@Gyom日付がすべての行に生成されるのを妨げません。シェルがすべての行を生成するのを防ぎます。bashでは、次のようなことを追加timestamp() { while read line; do echo "$(date) $line"; done; }; export -f timestampします。
smbear 2015年

サブプロセスとして日付を呼び出すことは、すべての行に対して日付を生成することを意味しますが、最初にスクリプトを起動します。
Peter Hansen

3
dateすべての行でコマンドが生成されないようにするにはprintf%(datespec)T形式で組み込みのbashを使用してみてください。したがって、次のようになりtimestamp() { while IFS= read -r line; do printf "%(%F %T)T %s\n" -1 "$line"; done; }ます。シェルのビルトインは生成されません。Datespec形式はstrftime(3)ie date形式に似ています。これにはbashが必要ですが、どのバージョンがそのprintf指定子をサポートしているかは不明です。
Mindaugas Kubilius

1

免責事項:私が提案しているソリューションは、Unixの組み込みユーティリティではありません。

私は数日前に同様の問題に直面しました。上記のソリューションの構文と制限が気に入らなかったので、すぐにGoでプログラムを作成して、仕事をしました。

ここでツールを確認できます:preftime

GitHubプロジェクトのリリースセクションには、Linux、MacOS、Windows用のビルド済み実行可能ファイルがあります。

このツールは不完全な出力行を処理し、(私の観点から)よりコンパクトな構文を持っています。

<command> | preftime

理想的ではありませんが、誰かを助けるために共有したいと思います。


0

でそれをやってdatetrしてxargsOSXに:

alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S\" | tr \"\n\" \" \"; echo \"{}\"'"
<command> | predate

ミリ秒が必要な場合:

alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"

ただし、OSXでは、dateでは%Nオプションが提供されないため、gdate(brew install coreutils)をインストールする必要があるため、最終的には次のようになります。

alias predate="xargs -I{} sh -c 'gdate +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"

-1

先頭に追加する値がすべての行で同じである場合は、ファイルでemacsを起動してから、次のようにします。

Ctrl + <space>

(そのスポットをマークするために)ファイルの先頭でスクロールし、最後の行の先頭までスクロールします(Alt +>はファイルの最後に移動します...おそらくShiftキーも含まれ、次にCtrl + aでその行の先頭に移動)および:

Ctrl + x r t

これは、指定した長方形(幅0の長方形)に挿入するコマンドです。

2008-8-21 18:45 PM <Enter>

または、先頭に追加するものは何でも...すると、幅0の長方形内のすべての行の先頭にテキストが追加されます。

更新:同じ日付が必要ないことに気付いたので、これは機能しません...少し複雑なカスタムマクロを使用してemacsでこれを実行できる場合もありますが、このような長方形の編集は知ってかなりいい...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.