2013-04-18 48 views
1

假設我有一個文本文件,其中包含以下格式的記錄,其中FS通常是逗號,而RS通常是換行符。是否可以在awk中處理包含換行符的字段?

但是,此規則的例外是,如果某個字段位於引號內,則應將換行符和逗號視爲該字段的一部分。

"This field contains 
line breaks and is 
quoted but it 
should be treated as a 
single field",1,2,3,"another field" 

如何使用awk來正確地分析這樣的文件,在那裏我仍然可以訪問$1,$2...,因爲我通常會,但與場上面的解釋呢?

我已經看過this wiki page,但在那裏提出的解決方案並沒有解決換行問題。

+2

這可能是可能的,但它會非常脆弱。 awk與大多數unix工具一樣,被設計用來處理數據(不格式化),一次一行。打破與你的工具集「契約」導致整個世界的痛苦。當你需要引用$ 1等時,我真的不知道提供任何類型的黑客。我會很高興被證明是錯誤的;-)前置和後置過濾器使用類似於&#*^@的東西來平整記錄,因爲替換\ n是唯一想到的事情。祝你好運。 – shellter

+0

這不像看起來那麼微不足道...... awk是唯一的選擇嗎? –

+0

不,我可以用Python編寫它,但對於這個問題,它似乎是awk的分隔符問題,而不是一些更基本的限制,所以我想嘗試使它在awk中工作。 – merlin2011

回答

0

一個可能的,但不完美的解決方案是:awk 'BEGIN{RS="\""}{...}'。通過這樣做,您可以將記錄分隔符重置爲",而字段分隔符仍爲空格。問題是這將爲您的文件添加兩個空記錄,因爲第一個和最後一個"將匹配爲分隔一些記錄。

例如:當通過增加condtion NR>1應用到您的數據

END OF RECORD - 
This field contains 
line breaks and is 
quoted but it 
should be treated as a 
single field END OF RECORD This - field 
,1,2,3, END OF RECORD ,1,2,3, - 
another field END OF RECORD another - field 

END OF RECORD - 

您可以跳過第一個

awk 'BEGIN{RS="\""} {print $0,"END OF RECORD",$1,"-",$2}' 

會產生這樣的結果。最後一個更棘手一些,因爲你不知道文件中有多少記錄。您可以將要打印的值保存到數組中,並在END語句中使用for循環打印它們,從而跳過文件中的第一個和最後一個記錄。

0

要讓awk正確解析文件,可以使用我編寫的名爲csvquote的程序,它暫時替換引號字段中出現的不含awk的非打印字符的逗號和換行符。該程序將數據轉換爲awk可以依賴逗號總是表示字段分隔符的格式,並且新行總是表示記錄分隔符。

要使用它,你換你的管道,涉及切割/ AWK/...這樣的:

csvquote /tmp/foo.csv | tail +2 | awk -F, '{print $3 $2}' | csvquote -u 

您可以在這裏找到代碼:https://github.com/dbro/csvquote

一個需要注意的是,如果你想在字段內搜索逗號和換行符,這使得該任務更加複雜,因爲您需要搜索非打印字符。如果您正在尋找更容易的方法,您應該查看csvfix工具。

另一個選擇是使用awk的FPAT,但如果這些字段包含轉義的引號則不起作用。請參閱http://www.gnu.org/software/gawk/manual/html_node/Splitting-By-Content.html

0

您可以使用雙重新行作爲記錄分隔符。如果還設置逗號作爲字段分隔符,那麼這可以讓你處理文本的每個塊作爲一個字段:

awk -v RS="\n\n" -v FS="," '...' file 

爲了您指定的文件,讓我們一起顯示文件編號與文件本身:

$ awk -v RS="\n\n" -v FS="," '{for (i=1; i<=NF; i++) print i, $i}' file 
1 "This field contains 
line breaks and is 
quoted but it 
should be treated as a 
single field" 
2 1 
3 2 
4 3 
5 "another field" 
+0

這似乎不適用於多個記錄,因爲您需要雙換行符分隔,並且原始問題需要單個換行符分隔符。 – merlin2011

+0

是的,如果記錄用雙重新行分隔,它就會工作。我會試圖找出一個更好的解決方案,讓我們看看我是否設法:) – fedorqui

相關問題