2015-04-24 49 views
1

我有每行包含看起來像這樣的多個部分JSON行:餵養通過命令sed的匹配塊

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

我想每次出現時轉換中的所有線路爲更人類可讀:

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

我試過使用sed把匹配的塊(在這種情況下是時間戳)放入日期命令的參數列表中。這失敗了。

$ echo '"SomeDate":"Date(-2156284800000)",' | \ 
    sed "s/Date(\([0-9\-]*\)[0-9][0-9][0-9])/$(date [email protected]\\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 [email protected]\\1 \"+%F %T\")/g" 

"SomeDate":"date [email protected] "+%F %T"", 


$ date [email protected] "+%F %T" 

1901-09-03-00:19:32 

爲什麼無法按預期運行的第一個命令?

我現在最好的猜測是,subshel​​l首先執行沒有\ 1替換,然後結果輸出實際上由sed使用。

我該如何實現我想要做的?

P.S.我使用CentOS的6.6

+0

注意到你打開一個子shell執行的命令,所以大概值不「到」有。另外,要在'sed'中執行一個命令,你需要'/ e'。 – fedorqui

+0

如果你用'-2156284800'代替'\\ 1',你會看到它的工作原理,顯示'\\ 1'與之前的字符串不匹配,原因在於@fedorqui描述的原因。 Fedorqui,你不需要'/ e',因爲這對我有用? –

+0

我試過gnu sed的'e'選項。 回聲「bla foo bla foo」| sed -e「s @(foo)@echo XX \ 1XX @ e」 所需輸出:bla XXfooXX bla XXfooXX 實際輸出:sh:bla:找不到命令 –

回答

0

如何用awk:

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

免責聲明:有可能是一個更好的方式來做到這一點,但簡要地說:

  • gensub就像gsub但給你訪問到匹配的組
  • 捕獲日期(XXX)位與:

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

    (它可以獲取實際曆元的匹配組\1中)

  • 第二個參數是:

    ("date [email protected]\\1 \"+%F %T\"" |& getline t) ? t : "\\1" 
    

    其形成的時間命令,運行它(與getline),並將結果指定變量tgetline,成功返回1,所以我們用三元(?:)語句檢查該語句,並返回該命令的第一行輸出。

  • 最後,我們告訴gensub是全局性的。

+0

Awk有一個已知的錯誤,並給出1970年以前的日期的錯誤答案。你的腳本給出「SomeDate」:「1970-01-01 01:00:01」, –

+0

哦,煩人。無論是perl,還是將awk壓入shell都可能是最好的路線呢? –

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