您的FPAT 要求每个字段至少包含一个字符,但您希望识别具有零个字符的空字段。添加允许零字符的FPAT 的替代方案:
gawk 'BEGIN { FPAT = "([^,]+)|(\"[^\"]+\")|" }
{ printf "%d:%d:", NR, NF; for (i = 1; i <= NF; i++) printf("[%s]", $i); print "" }'
注意FPAT 末尾的额外|。该操作仅标识记录号、字段数,并用方括号将每个字段的值括起来。
当您的数据字符串提供给该脚本时,输出为:
1:8:["RAM"]["31st street, Bengaluru, India"][][][]["7865431234"][]["VALID"]
这四个空字段显示得很清楚。
现在你要做的就是处理:
"Mr ""Manipulator"", the Artisan","29th Street, Delhi, India",,,"",,,"INVALID"
引用值中有双引号。这并不难管理:
gawk 'BEGIN { FPAT = "([^,]+)|(\"([^\"]|\"\")*\")[^,]*|" }
{ printf "%d:%d:", NR, NF; for (i = 1; i <= NF; i++) printf("%d[%s]", i, $i); print "" }' "$@"
FPAT 表示一个字段是:
-
一系列非逗号,
-
或者它是以双引号开头的字段,包含零个或多个实例:
后跟双引号和可选的非逗号数据
-
或者它是空的
请注意,“可选非逗号数据”应为空,并且仅出现在格式错误的 CSV 数据中。
给定输入数据:
"RAM","31st street, Bengaluru, India",,,,"7865431234",,"VALID"
"Mr ""Manipulator"", the Artisan","29th Street, Delhi, India",,,,,,"INVALID"
"Some","","Empty","",Fields "" Wrapped,"",in quotes
"Malformed" CSV,Data,"Note it has data after" a close quote,"and before a comma,",,"INVALID"
这会产生:
1:8:1["RAM"]2["31st street, Bengaluru, India"]3[]4[]5[]6["7865431234"]7[]8["VALID"]
2:8:1["Mr ""Manipulator"", the Artisan"]2["29th Street, Delhi, India"]3[]4[]5[]6[]7[]8["INVALID"]
3:7:1["Some"]2[""]3["Empty"]4[""]5[Fields "" Wrapped]6[""]7[in quotes]
4:6:1["Malformed" CSV]2[Data]3["Note it has data after" a close quote]4["and before a comma,"]5[]6["INVALID"]
请注意,字段编号作为括号数据的前缀包含在内(因此我稍微调整了打印格式)。
关于此不处理的唯一格式是可以在字段数据中嵌入换行符的格式——根据基于行的输入的性质,它假定没有字段被拆分为多行。 (这也意味着它不会正确识别以双引号开头并且在行尾之前没有匹配的双引号的字段。我想您可以添加一个替代方法来识别它。最好只是使数据正确。)
请注意Sobrique 的answer 中的建议,以使用旨在处理 CSV 的工具来处理 CSV。这通常是一个好主意,你必须处理的变化集越复杂,它的想法就越好。这接近于您应该考虑使用的复杂正则表达式。另请注意,尽管RFC 4180 正式而严格地定义了一个 CSV 版本,但有多个程序(包括 MS Office)可以处理不同但相关的格式。