这个问题的目的是提供一个规范的答案.
给定可能由Excel或其他具有嵌入换行符的工具生成的CSV,嵌入式双引号和空字段,如:
$ cat file.csv
"rec1, fld1",,"rec1"",""fld3.1
"",
fld3.2","rec1
fld4"
"rec2, fld1.1
fld1.2","rec2 fld2.1""fld2.2""fld2.3","",rec2 fld4
Run Code Online (Sandbox Code Playgroud)
使用awk识别单独记录和字段的最有效方法是什么:
Record 1:
$1=<rec1, fld1>
$2=<>
$3=<rec1","fld3.1
",
fld3.2>
$4=<rec1
fld4>
----
Record 2:
$1=<rec2, fld1.1
fld1.2>
$2=<rec2 fld2.1"fld2.2"fld2.3>
$3=<>
$4=<rec2 fld4>
----
Run Code Online (Sandbox Code Playgroud)
所以它可以在awk脚本的其余部分内部用作那些记录和字段.
有效的CSV将符合RFC 4180或可由MS-Excel生成.
解决方案必须允许记录结束只是LF(\n),这是UNIX文件的典型情况,而不是CRLF(\r\n),正如标准所要求的那样,Excel或其他Windows工具会生成.它还可以容忍与引用字段混合的未加引号的字段.它特别不需要容忍"使用前面的反斜杠转义s(即\"代替""),因为其他一些CSV格式允许 - 如果你有,那么添加一个gsub(/\\"/,"\"\"")前端将处理它并尝试在一个脚本中自动处理两个转义机制将使脚本不必要地脆弱和复杂.
你如何使用gawk解析CSV文件?简单设置FS=","是不够的,因为带有逗号的引用字段将被视为多个字段.
使用的示例FS=","不起作用:
文件内容:
one,two,"three, four",five
"six, seven",eight,"nine"
Run Code Online (Sandbox Code Playgroud)
gawk脚本:
BEGIN { FS="," }
{
for (i=1; i<=NF; i++) printf "field #%d: %s\n", i, $(i)
printf "---------------------------\n"
}
Run Code Online (Sandbox Code Playgroud)
输出不好:
field #1: one
field #2: two
field #3: "three
field #4: four"
field #5: five
---------------------------
field #1: "six
field #2: seven"
field #3: eight
field #4: "nine"
---------------------------
Run Code Online (Sandbox Code Playgroud)
期望的输出:
field #1: one
field #2: two
field #3: "three, four"
field #4: five
---------------------------
field #1: "six, seven"
field …Run Code Online (Sandbox Code Playgroud)