一個稍微複雜的awk & sed應用

最近做了一個文本 CDR 轉換器,從 A 樣式轉換爲 B 樣式,如下所示。

 

A 樣式

 

B 樣式

 

 

A 樣式到 B 樣式的轉換要點如下:

1.     header trailer 都可直接轉換,但是 B 樣式需要加上 CDR 的計數

2.     B 樣式的 header 還含有 record type ,需要從 A 樣式的某個註釋行中獲取

3.     字段域的轉換比較簡單,都是一行對一行

4.     A 樣式有註釋行,轉換時要全部刪除

 

轉換由 awk sed 完成,完整的命令是這樣的:

awk 'BEGIN { cnt=0; } { if ( $0 == "RECORD" ) { cnt++; printf("Record (%d)/n", cnt); } else if ( $0 == "." ) { printf("End of Record (%d)/n", cnt); } else { print $0; } }' layout_a | sed '/^Record/{N;N;N;s//n//g;}' | sed 's/^/(Record (.*)/).*input_type /(.*/)$//1 "/2"/;s/^F /(.*/) /(.*/)$/   "/1" = "/2"/;/^#/d' > layout b

 

具體解析如下:

1.    awk 'BEGIN { cnt=0; } { if ( $0 == "RECORD" ) { cnt++; printf("Record (%d)/n", cnt); } else if ( $0 == "." ) { printf("End of Record (%d)/n", cnt); } else { print $0; } }' layout_a | sed '/^Record/{N;N;N;s//n//g;}' | sed 's/^/(Record (.*)/).*input_type /(.*/)$//1 "/2"/;s/^F /(.*/) /(.*/)$/   "/1" = "/2"/;/^#/d' > layout b

判斷 CDR header trailer 。如果是 header ,即該行內容爲 ”RECORD” ,計數器加一,且輸出 ”Record (?)” 到下一步;如果是 trailer ,即該行內容爲 ”.” ,輸出 ”End of Record (?)” 到下一步;否則,不作修改輸出到下一步。

2.    awk 'BEGIN { cnt=0; } { if ( $0 == "RECORD" ) { cnt++; printf("Record (%d)/n", cnt); } else if ( $0 == "." ) { printf("End of Record (%d)/n", cnt); } else { print $0; } }' layout_a | sed '/^Record/{N;N;N;s//n//g;}' | sed 's/^/(Record (.*)/).*input_type /(.*/)$//1 "/2"/;s/^F /(.*/) /(.*/)$/   "/1" = "/2"/;/^#/d' > layout b

遇到 header ,合併後續三行。因爲第四行保留了該 CDR Record type

3.    awk 'BEGIN { cnt=0; } { if ( $0 == "RECORD" ) { cnt++; printf("Record (%d)/n", cnt); } else if ( $0 == "." ) { printf("End of Record (%d)/n", cnt); } else { print $0; } }' layout_a | sed '/^Record/{N;N;N;s//n//g;}' | sed ' s/^/(Record (.*)/).*input_type /(.*/)$//1 "/2"/ ; s/^F /(.*/) /(.*/)$/   "/1" = "/2"/;/^#/d' > layout b

從上一步生成的 header 提取合適的內容,形成 B 樣式的 header 。注意括號的運用。

4.    awk 'BEGIN { cnt=0; } { if ( $0 == "RECORD" ) { cnt++; printf("Record (%d)/n", cnt); } else if ( $0 == "." ) { printf("End of Record (%d)/n", cnt); } else { print $0; } }' layout_a | sed '/^Record/{N;N;N;s//n//g;}' | sed 's/^/(Record (.*)/).*input_type /(.*/)$//1 "/2"/; s/^F /(.*/) /(.*/)$/   "/1" = "/2"/; /^#/d' > layout b

提取各個字段的鍵和值,並加上雙引號,形成 B 樣式的字段域。同樣注意括號的運用。

5.    awk 'BEGIN { cnt=0; } { if ( $0 == "RECORD" ) { cnt++; printf("Record (%d)/n", cnt); } else if ( $0 == "." ) { printf("End of Record (%d)/n", cnt); } else { print $0; } }' layout_a | sed '/^Record/{N;N;N;s//n//g;}' | sed 's/^/(Record (.*)/).*input_type /(.*/)$//1 "/2"/;s/^F /(.*/) /(.*/)$/   "/1" = "/2"/; /^#/d ' > layout b

刪除剩餘的註釋行。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章