1

假设我有一个包含以下格式记录的文本文件,其中 theFS通常是逗号,而 theRS通常是换行符。

但是,此规则的例外是,如果字段用引号引起来,则应将换行符和逗号视为字段的一部分。

"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...像往常一样访问,但使用上述字段解释?

我已经看过这个 wiki 页面,但是那里提出的解决方案并没有解决换行问题。

4

3 回答 3

0

要让 awk 正确解析文件,您可以使用我编写的名为 csvquote 的程序,该程序临时用不会混淆 awk 的非打印字符替换出现在引用字段中的逗号和换行符。该程序将数据整理成一种格式,其中 awk 可以依赖始终表示字段分隔符的逗号和始终表示记录分隔符的换行符。

要使用它,您可以像这样包装涉及 cut/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

于 2013-05-18T20:55:44.713 回答
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"
于 2014-11-12T10:09:54.340 回答
0

一个可能的,虽然不是完美的,解决方案是这样的awk 'BEGIN{RS="\""}{...}':通过这样做,您将记录分隔符重置为",而字段分隔符仍然是空格。问题是这会在您的文件中添加两个空记录,因为第一个和最后一个"将被匹配为分隔一些记录。

例子:

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

应用于您的数据时将产生此结果

 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  - 

您可以通过添加条件来跳过第一个NR>1。最后一个有点棘手,因为您不知道文件中有多少记录。您可以将要打印的值保存在数组中,并for在语句中使用循环打印它们END,跳过文件中的第一条和最后一条记录。

于 2013-04-27T16:04:32.167 回答