ユニバーサルテキストファイルのすべてのUnixタイムスタンプ(ミリ秒単位)を人が読める日付に変換します。

ユニバーサルテキストファイルのすべてのUnixタイムスタンプ(ミリ秒単位)を人が読める日付に変換します。

プレーンテキストファイルのUnix Epoch(ミリ秒)を通常の日付に変更したいと思います。私はbash、sed、awk、perlのソリューションを受け入れます。

サンプルファイル1(13桁のみ):

Foo bar 1397497040418 foo 1526 bar foobar, bar 1397497060518.
Bar, 1357407040418 foo 10 foobar.

私は次のような出力が欲しい。

Foo bar 2014-04-14 19:37:20 foo 1526 bar foobar, bar 2014-04-14 19:37:40.
Bar, 2013-01-05 18:30:40 foo 10 foobar.

私の試みが失敗しました:

sed -E "s/([0-9]{10})/date -d @\1/;e" file1

どんなアイデアがありますか?

ありがとうございます。

答え1

入力ファイルを使用してください。

perl -MTime::Piece -pe '
    s{ \b (\d{10}) \d{3}\b }
     { localtime($1)->strftime("%F %T") }xge
' file1
Foo bar 2014-04-14 13:37:20 foo 1526 bar foobar, bar 2014-04-14 13:37:40.
Bar, 2013-01-05 12:30:40 foo 10 foobar.

答え2

追加の数字を無視して日付変換を最初の10桁に制限したいと仮定すると(つまり、日付が数十万年後ではないことを意味する場合)、GNUを使用して次のようにすることdateができますperl

$ perl -pe 's/\b(\d{10})\d{3}\b/chomp($i=`date -d \@$1 "+%F %T"`);$i/eg' file1 
Foo bar 2014-04-14 18:37:20 foo 1526 bar foobar, bar 2014-04-14 18:37:40.
Bar, 2013-01-05 17:30:40 foo 10 foobar.

グレンのソリューションしかし、よりきれいで移植性が高いので、Perlモジュールを使用することが気に入らない場合(そしてそうしてはいけません)、私は私よりもこのモジュールをお勧めします。


あなたのsed試みに関しては結果コマンドにはバックティックまたはを使用する必要があります$(command)。今はほぼすべて来ました。

$ sed -E "s/([0-9]{10})/$(date -d @\1)/" file1
Foo bar Thu 01 Jan 1970 01:00:01 AM BST418 foo 1526 bar foobar, bar 1397497060518.
Bar, Thu 01 Jan 1970 01:00:01 AM BST418 foo 10 foobar.

もちろん、これは余分な数字を削除せず、13桁に制限することもありませんが、必要なものが明確に指定されていないので、修正方法がわかりません。私のPerlソリューションはこれを処理するので、削除したくない場合はsedを使用できます。

答え3

と機能awkでGNUを使用してください。 EPOCHタイムスタンプなので、指定された行をスキャンして10以上の数字を含むレコードを識別します。match()substr()strftime()

このレコードから最初の10桁だけを抽出してstrftime()関数に渡し、必要に応じて日付形式を適用します。この機能を使用して、元のレコードを新しいタイムスタンプに置き換えますsub()

awk '
{ 
    for(col=1; col<=NF; col++) { 
        if ( match($col, /[[:digit:]]{10,}/) ) { 
            sub( substr($col, RSTART, RLENGTH), 
              strftime("%Y-%m-%d %H:%M:%S", substr($col, RSTART, RLENGTH-3) ) )   
        }  
    }
}1' file1

答え4

GNU awk時間関数の場合、match()と単語境界の3番目の引数は次のとおりです。

$ awk '{
    while ( match($0,/(.*)\<([0-9]{10})[0-9]{3}\>(.*)/,a) ) {
        $0 = a[1] strftime("%F %T",a[2]) a[3]
    }
    print
}' file
Foo bar 2014-04-14 12:37:20 foo 1526 bar foobar, bar 2014-04-14 12:37:40.
Bar, 2013-01-05 11:30:40 foo 10 foobar.

関連情報