我使用awk用“,”解析我的数据作为分隔符,因为输入是一个csv文件。但是,数据中有“,”用双引号(“...”)转义。
实施例
filed1,filed2,field3,"field4,FOO,BAR",field5
如何在双引号中忽略逗号“,”以便我可以使用awk正确解析输出?我知道我们可以在excel中做到这一点,但我们如何在awk中做到这一点?
答案 0 :(得分:22)
使用 GNU awk 4 :
很容易zsh-4.3.12[t]% awk '{
for (i = 0; ++i <= NF;)
printf "field %d => %s\n", i, $i
}' FPAT='([^,]+)|("[^"]+")' infile
field 1 => filed1
field 2 => filed2
field 3 => field3
field 4 => "field4,FOO,BAR"
field 5 => field5
根据OP要求添加一些注释。
来自GNU awk manual on "Defining fields by content:
FPAT的值应该是一个提供常规字符串的字符串 表达。这个正则表达式描述了每个的内容 领域。在如上所述的CSV数据的情况下,每个字段是 “任何不是逗号的东西”,或“双引号,任何东西 这不是一个双引号,而是一个收尾双引号。“如果写成 正则表达式常量,我们将
/([^,]+)|("[^"]+")/
。把它写成一个字符串 要求我们逃避双引号,导致:
FPAT = "([^,]+)|(\"[^\"]+\")"
使用+
两次,这对空字段无效,但也可以修复:
如上所述,用于FPAT的正则表达式要求每个字段至少包含一个字符。直接修改(将第一个“
+
”更改为“*
”)允许字段为空:
FPAT = "([^,]*)|(\"[^\"]+\")"
答案 1 :(得分:11)
当引号字段中有换行符和逗号时,FPAT有效,但是当有双引号时则不行,如下所示:
field1,"field,2","but this field has ""escaped"" quotes"
您可以使用我编写的一个名为csvquote的简单包装程序,使awk能够轻松解释数据,然后恢复有问题的特殊字符,如下所示:
csvquote inputfile.csv | awk -F, '{print $4}' | csvquote -u
请参阅https://github.com/dbro/csvquote了解代码和文档
答案 2 :(得分:1)
完全成熟的CSV解析器(如Perl的Text::CSV_XS
)专门用于处理这种奇怪现象。
假设您只想打印第4个字段:
perl -MText::CSV_XS -lne 'BEGIN{$csv=Text::CSV_XS->new()} if($csv->parse($_)){ @f=$csv->fields(); print "\"$f[3]\"" }' file
输入行分为数组@f
字段4是$f[3]
,因为Perl开始索引为0
我在答案中提供了Text::CSV_XS
的更多解释:parse csv file using gawk