我正在使用 awk 以“,”作为分隔符解析我的数据,因为输入是一个 csv 文件。但是,数据中有“,”,由双引号(“...”)转义。
例子
filed1,filed2,field3,"field4,FOO,BAR",field5
如何忽略双引号中的逗号“,”以便可以使用 awk 正确解析输出?我知道我们可以在 excel 中做到这一点,但我们如何在 awk 中做到这一点?
我正在使用 awk 以“,”作为分隔符解析我的数据,因为输入是一个 csv 文件。但是,数据中有“,”,由双引号(“...”)转义。
例子
filed1,filed2,field3,"field4,FOO,BAR",field5
如何忽略双引号中的逗号“,”以便可以使用 awk 正确解析输出?我知道我们可以在 excel 中做到这一点,但我们如何在 awk 中做到这一点?
使用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 要求添加一些注释。
FPAT 的值应该是一个提供正则表达式的字符串。这个正则表达式描述了每个字段的内容。在上述 CSV 数据的情况下,每个字段要么是“非逗号的任何内容”,要么是“双引号、非双引号的任何内容以及结束双引号”。如果写成正则表达式常量,我们将有
/([^,]+)|("[^"]+")/
. 将其写为字符串需要我们转义双引号,从而导致:
FPAT = "([^,]+)|(\"[^\"]+\")"
使用+
两次,这对于空字段不能正常工作,但它也可以修复:
如前所述,用于 FPAT 的正则表达式要求每个字段至少包含一个字符。直接修改(将第一个 '<code>+' 更改为 '<code>*')允许字段为空:
FPAT = "([^,]*)|(\"[^\"]+\")"
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
Perl 等成熟的 CSV 解析器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