3 回答
TA贡献1712条经验 获得超3个赞
使用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手册“按内容定义字段:
FPAT的值应该是提供正则表达式的字符串。此正则表达式描述每个字段的内容。对于上面显示的CSV数据,每个字段要么是“不是逗号的任何内容”,要么是“双引号,任何不是双引号的内容和右双引号。”如果以正则表达式形式编写不变,我们将有/([^,]+)|("[^"]+")/。将其写为字符串需要我们转义双引号,从而导致:
FPAT = "([^,]+)|(\"[^\"]+\")"
使用+两次,这不适用于空白字段,但也可以修复:
如所写,用于FPAT的正则表达式要求每个字段至少包含一个字符。直接修改(将第一个' +' 更改为' *')允许字段为空:
FPAT = "([^,]*)|(\"[^\"]+\")"
TA贡献1810条经验 获得超4个赞
诸如Perl这样的完全成熟的CSV解析器Text::CSV_XS是专门为处理这种怪异而构建的。
假设您只想打印第四个字段:
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开始索引
添加回答
举报