假设我有一个包含以下表单记录的文本文件,其中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,但是那里提出的解决方案并没有解决换行问题。
答案 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"