2

次のように、行ごとに複数の部分を含む json 行があります。

"SomeDate":"Date(-2156284800000)",

すべての行の各出現箇所を、より人間が読める形式に変換したいと思います。

"SomeDate":"1901-09-03 00:19:32",

sed を使用して、一致したブロック (この場合はタイムスタンプ) を date コマンドの引数リストに入れてみました。これは失敗します。

$ echo '"SomeDate":"Date(-2156284800000)",' | \
  sed "s/Date(\([0-9\-]*\)[0-9][0-9][0-9])/$(date -d@\\1 \"+%F %T\")/g"

date: invalid date `@\\1'
"SomeDate":"",

これをすべてデバッグしようとして、日付に「エコー」を追加して、実行する必要があるコマンドを検証しました

$ echo '"SomeDate":"Date(-2156284800000)",' | \
  sed "s/Date(\([0-9\-]*\)[0-9][0-9][0-9])/$(echo date -d@\\1 \"+%F %T\")/g"

"SomeDate":"date -d@-2156284800 "+%F %T"",


$ date -d@-2156284800 "+%F %T"

1901-09-03-00:19:32

最初のコマンドが期待どおりに実行されないのはなぜですか?

私が今持っている最良の推測は、サブシェルが最初に \1 置換なしで実行され、次に結果の出力が実際に sed によって使用されるということです。

自分がやろうとしていることをどのように達成できますか?

PS CentOS 6.6を使用しています

4

2 に答える 2

0

awk を使用する方法:

echo '"SomeDate":"Date(-2156284800000)",' | awk '{ print gensub(/Date\(([0-9\-]+)\)/, ("date -d@\\1 \"+%F %T\"" |& getline t) ? t : "\\1", "g"); }'

免責事項:おそらくこれを行うためのより良い方法がありますが、簡単に:

  • gensubgsubていますが、一致したグループにアクセスできます
  • Date(XXX) ビットを次のようにキャプチャします。

    /Date\(([0-9\-]+)\)/
    

    (一致グループ内の実際のエポックを取得します\1)

  • 2 番目の引数は次のとおりです。

    ("date -d@\\1 \"+%F %T\"" |& getline t) ? t : "\\1"
    

    これは date コマンドを形成し、それを ( でgetline) 実行し、結果を変数 に代入しますtgetline、奇妙に成功すると返されるため、 ternary ( ) ステートメント1でそれをチェックし、そのコマンドからの出力の最初の行を返します。?:

  • 最後に、gensubグローバルであることを伝えます。

于 2015-04-24T13:52:09.590 に答える
0

私が現在使用している回避策は、perl によるものです。

$ echo fee 4321432431 fie 1429882795 fum | \
       perl -MPOSIX -pe 's/(\d+)/strftime "%F", localtime $1/eg'


fee 2106-12-10 fie 2015-04-24 fum
于 2015-04-24T14:18:13.710 に答える