3

次のようなテキストストリームがあります。

----------------------------------------
s123456789_9780
  heartbeat:test       @ 1344280205000000: '0'
  heartbeat:test       @ 1344272490000000: '0'

これらの長い数値は、マイクロ秒単位のタイムスタンプです。これらのタイムスタンプをより人間が理解できる日付に変更するある種のパイプを介してこの出力を実行したいと思います。

タイムスタンプ(次のコロン付き)だけを指定すると、それを実行できるdateコマンドがあります。

$ date --date=@$(echo 1344272490000000: | sed 's/.......$//') +%Y/%d/%m-%H:%M:%S
2012/06/08-10:01:30

私はこのようなものになりたいです:

----------------------------------------
s123456789_9780
  heartbeat:test       @ 2012/06/08-12:10:05: '0'
  heartbeat:test       @ 2012/06/08-10:01:30: '0'

タイムスタンプを照合して、そのタイムスタンプでシェル関数を呼び出す値に置き換えることはできないと思いますsed(ただし、間違って表示されることを望んでいます)。おそらくawkそれを行うことができますか?私はあまりよく知らないawk

私にとってトリッキーに思えるもう1つの部分は、一致しない行を変更せずに通過させることです。

もちろん、これを行うPythonプログラムを作成することもできますが、可能であればこれをシェルに保持したいと思います(これはシェルスクリプト内で生成され、外部ファイルに依存しないようにします)。

4

5 に答える 5

3

これはうまくいくかもしれません(GNU sed):

sed '/@ /!b;s//&\n/;h;s/.*\n//;s#\(.\{10\}\)[^:]*\(:.*\)#date --date=@\1 +%Y/%d/%m-%H:%M:%S"\2"#e;H;g;s/\n.*\n//' file

説明:

  • /@ /!b@救済し、スペースが続く行を含まない行を印刷するだけです
  • s//&\n/上記のパターンの後に改行を挿入します
  • hパターン スペース (PS) をホールド スペース (HS) にコピーします。
  • s/.*\n//@スペースが続くまで削除
  • s#\(.\{10\}\)[^:]*\(:.*\)#date --date=@\1 +%Y/%d/%m-%H:%M:%S"\2"#ePS に残っているものから、最初の 10 文字と文​​字:列の最後までの後方参照を作成します。これらをdateコマンドに渡して、結果を PS に評価します。
  • HPS を HS に追加し、同時に改行を挿入する
  • gHS を PS にコピーする
  • s/\n.*\n//文字列の元の部分を削除します
于 2012-08-09T20:26:20.793 に答える
1

入力の空白を保持しながら、少しsedでbashします。

while read -r; do                                                                                                                                                                                                                                          
    parts=($REPLY)
    if [[ ${parts[0]} == "heartbeat:test" ]]; then
        dateStr=$(date --date=@${parts[2]%000000:} +%Y/%d/%m-%H:%M:%S)
        REPLY=$(echo "$REPLY" | sed "s#[0-9]\+000000:#$dateStr#")
    fi
    printf "%s\n" "$REPLY"
done
于 2012-08-09T17:18:18.373 に答える
1

どうですか:

while read s1 at tm s2
do 
    tm=${tm%000000:}
    echo $s1 $at $(date --date @$tm +%Y/%d/%m-%H:%M:%S)
done < yourfile
于 2012-08-09T17:16:17.800 に答える
1

私も解決策を見たいと思っていますsedが、それは私のsed-fuを少し超えています. awkサポートされているようstrftimeに、ここではかなり簡単です。

awk '
/^ *heartbeat/ { 
  gsub(".{7}$", "", $3)
  $3 = strftime("%Y/%d/%m-%T", $3)
  print " ", $1, $3
}

$0 !~ /heartbeat/' file

出力:

s123456789_9780
heartbeat:test 2012/06/08-21:10:05
heartbeat:test 2012/06/08-19:01:30

$3はマイクロ秒フィールドです。gsubタイムスタンプを秒に変換します。

$0 !~、ハートビート以外の行が確実に出力されるようにします ({ print }暗黙的にデフォルトのブロックです)。

于 2012-08-09T17:05:19.190 に答える
0

これは、ほとんどの場合、コマンドbashを使用して行います。date

#!/bin/bash
IFS=$
while read a ; do
case "$a" in
*" @ "[0-9]*) pre=${a% @ *}
              a=${a#$pre @ }
              post=${a##*:}
              a=${a%??????:$post}
              echo "$pre$(date --date=@$a +%Y/%d/%m-%H:%M:%S):$post"
              ;;
*)            echo "$a" ;;
esac
done <<.
----------------------------------------
s123456789_9780
  heartbeat:test       @ 1344280205000000: '0'
  heartbeat:test       @ 1344272490000000: '0'
.
于 2012-08-09T17:12:11.233 に答える