2014-07-09 152 views
0

這就是我需要做的。AWK打印不正確

我有一個文本文件,並使用awk解析它。輸出應該是json格式。它應該是這樣的:

{ 
"Record X" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record Y" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record Z" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record A" : { "Key1":"Value1", "Key2":"Value2"} 
} 

現在,這是文本文件的內容的樣子:

Record X 
    Key1 is Value1, Key2 is Value2 
Record Y 
    Key1 is Value1, Key2 is Value2 
Record Z 
    Key1 is Value1, Key2 is Value2 
Record A 
    Key1 is Value1, Key2 is Value2 

我試圖創建一個腳本來製作我想要的輸出,我在第一部分,但我已經卡在打印線。這是我的腳本:

awk 
'BEGIN { print "{" } 
     { if($0 ~ /^Record /){print "\"" $0 "\":" }} 
END { print "}" }' myRecord.txt 

和輸出是這樣的..

{ 
":ecord X 
":ecord Y 
":ecord Z 
":ecord A 
} 

我不明白爲什麼樣的腳本會產生類似的東西。 請告訴我什麼是錯的。謝謝!

回答

0

你的主要問題是,你的輸入文件創建於Windows並且在每行的末尾有control-Ms在打印行時會導致損壞。在運行腳本之前,使用dos2unix或類似工具刪除它們。不要使用下面建議的任何getline解決方案,因爲這將是錯誤的方法,並引入了很多警告和複雜性(請參閱http://awk.info/?tip/getline)。

試試這個:

$ cat tst.awk 
BEGIN{ print "{" } 
NR%2 { id = $0; next } 
{ 
    sub(/^ +/,"") 
    gsub(/ is /,"\":\"") 
    gsub(/, /,"\", \"") 
    printf "%s\"%s\" : { \"%s\"}", (c++?",\n":""), id, $0 
} 
END{ print "\n}" } 

$ awk -f tst.awk file 
{ 
"Record X" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record Y" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record Z" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record A" : { "Key1":"Value1", "Key2":"Value2"} 
} 
+0

而不是'printf'%s \「%s \」:{\「%s \ 「}」,(C++?「,\ n」:「」),id,$ 0'您可以使用'printf(C++?「,\ n」:「」)「\」%s \「:{\ %s \「}」,id,$ 0'。這有什麼優點或缺點嗎? – Jotne

+0

是的,你是對的!問題在於控件M或其他因爲文本文件是在Windows中創建的。大多數人認爲問題出在代碼中,多虧了你! :) – user3714598

+0

@Jotne大多數情況下,我只是覺得使用字符串連接來創建格式字符串混淆了代碼。 –

0

您可以通過awk的getline函數的做到這一點,

$ awk 'BEGIN{printf "{\n"}/^Record/{var=$0; getline; w=$1; x=$3; y=$4; z=$6;}{printf "\""var"\"" " : { ""\""w"\""":\""x"\", \""y"\":\""z"\"},\n"} END{printf "}\n"}' file 
{ 
"Record X" : { "Key1":"Value1,", "Key2":"Value2"}, 
"Record Y" : { "Key1":"Value1,", "Key2":"Value2"}, 
"Record Z" : { "Key1":"Value1,", "Key2":"Value2"}, 
"Record A" : { "Key1":"Value1,", "Key2":"Value2"}, 
} 

通過GNU awk的gsub功能,

$ awk -v RS="Record" 'BEGIN{print "{"} gsub(/\n/,"",$0){gsub(/.$/,"",$4); print "\""RS" "$1"\" : { \""$2"\":\""$4"\", \""$5"\":\""$7"\"},"} END{print "}"}' file 
{ 
"Record X" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record Y" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record Z" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record A" : { "Key1":"Value1", "Key2":"Value2"}, 
} 
+0

最後一個比較好,因爲它不使用'getline',但在最後一行仍然有''''額外的。你需要提到你需要'gnu awk',因爲'RS'中有多個字符(普通'awk'支持最多一個字符) – Jotne

+0

我只是把我的帖子改成了'/^Record/{a = $ 0; next}以避免出現其他線路時出現的問題,這也可以用來代替'getline',並且比'RS =「Record」'更便攜。我建議你從'gsub(/.$/,"",$ 4)'改爲'gsub(/,$ /,「」,$ 4)''。 '''刪除了最後一個字符,但是你只想刪除'',''' – Jotne

+0

@Jotne'$ 4'中的最後一個字符必須是',',所以我把'.'放在了模式中。 –

1

這裏是另一個awk不使用getline

awk -F"[ ,]*" 'BEGIN {print "{"} /^Record/ {a=$0;next} {print "\""a"\" : { \""$2"\":\""$4"\", \""$5"\":\""$7"\"},"} END {print "}"}' 
{ 
"Record X" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record Y" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record Z" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record A" : { "Key1":"Value1", "Key2":"Value2"}, 
} 

如果你得到最後的問題,你可以這樣做:

awk -F"[ ,]*" -v f=$(cat file | wc -l) 'BEGIN {print "{"} /^Record/ {a=$0;next} {print "\""a"\" : { \""$2"\":\""$4"\", \""$5"\":\""$7"\"}"(NR==f?"":",")} END {print "}"}' file 
{ 
"Record X" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record Y" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record Z" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record A" : { "Key1":"Value1", "Key2":"Value2"} 
} 

或全部僅awk

awk -F"[ ,]*" 'BEGIN {print "{"} FNR==NR {f=NR;next} /^Record/ {a=$0;next} {print "\""a"\" : { \""$2"\":\""$4"\", \""$5"\":\""$7"\"}"(FNR==f?"":",")} END {print "}"}' file{,} 
{ 
"Record X" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record Y" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record Z" : { "Key1":"Value1", "Key2":"Value2"}, 
"Record A" : { "Key1":"Value1", "Key2":"Value2"} 
} 
0

使用您的流邏輯:

awk 'BEGIN { print "{" } 
     /^Record /{ 
      if (c){printf ",\n"} 
      printf("\"%s\":",$0);next} 
      { 
      gsub("is",":") 
      gsub(" *","\"") 
      printf(" {%s\"}",$0) 
      c++ 
      } 
     END { print "\n}" }' infile 
+1

聰明的方式來處理不顯示','在最後一行:) – Jotne