是否可以在awk中处理包含换行符的字段?

时间:2013-04-18 22:22:30

标签: text csv awk newline gawk

假设我有一个包含以下表单记录的文本文件,其中FS通常是逗号,而RS通常是换行符。

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

"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,但是那里提出的解决方案并没有解决换行问题。

3 个答案:

答案 0 :(得分: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循环打印它们,跳过文件中的第一个和最后一个记录。

答案 1 :(得分: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

答案 2 :(得分: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"