这个 awk 应该能够处理带引号的字段,并且也适用于转义引号,无论这些字段出现在哪里。
awk '{while(match($0,/"[^"]+",|([^,]+(,|$))/,a)){
$0=substr($0,RSTART+RLENGTH);b[++x]=a[0]}
print b[1] b[4];x=0}' file
Input
"abc@xyz.com,www.example.com",field2,field3,field4
"def@xyz.com",field2,field3,field4
field1,"abc@xyz.com,www.example.com",field3,field4
输出
"abc@xyz.com,www.example.com",field4
"def@xyz.com",field4
field1,field4
它甚至可以在
field1,"field,2","but this field has ""escaped"\" quotes",field4
强大的FPAT变量在某些情况下会失效!
解释
while(match($0,/"[^"]+",|([^,]+(,|$))/,a))
开始一个while循环,只要匹配成功(即存在一个字段),就会继续。
该匹配将匹配正则表达式的第一个出现,并恰好匹配字段并将其存储在数组a
中。
$0=substr($0,RSTART+RLENGTH)
将
$0
设置为从匹配字段的结尾开始,并将匹配字段添加到
b
对应数组位置。
print b[1] b[4]
打印你想要的b
字段,并将x设置为零以便下一行使用。
缺陷
如果字段同时包含转义引号和逗号,则会失败。
编辑
更新以支持空字段。
awk '{while(match($0,/("[^"]+",|[^,]*,|([^,]+$))/,a)){
$0=substr($0,RSTART+RLENGTH);b[++x]=a[0]}
print b[1] b[4];x=0}' file
perl -lnE 'while(/([^,]*)|("[^"]+")/g){say "#$1#"}' <<<'Robbins,Arnold,"1234 A Pretty Street, NE",MyTown,MyState,12345-6789,USA'
- Johannes Riecken"1234 A Pretty Street和NE"
上作为2个单独的字符串进行匹配似乎是错误的,因为上面的awk和grep -Eo '([^,]*)|("[^"]+")' <<<'Robbins,Arnold,"1234 A Pretty Street, NE",MyTown,MyState,12345-6789,USA'
都将"1234 A Pretty Street, NE"
识别为一个单一的字符串。当然,那个perl脚本可能包含一些神奇的咒语,意味着“不要匹配最左边最长的”,我不知道,因为我不懂perl语法。 - Ed Morton