关于“输入文件包含 Control M 字符,我已经使用 dos2unix 删除了”——这可能会让你的生活更加艰难。一行中的“换行符”很有可能只是LF
s 而记录结尾是CRLF
,因此通过删除CR
s 我们不能再简单地将 awk 设置RS
为CRLF
然后删除LF
记录中剩余的任何 s。
如果您的文件是按照您在问题下的评论中所说的那样从 Excel 导出的,那么无论字段是否被引用,它将CRLF
在每条记录的末尾使用,并且LF
如果您只是不使用,则单独在每个字段中使用不要dos2unix
在上面运行:
$ cat -v test.csv
234,aa,bb,cc,30,dd^M
22,cc,
ff,dd,
40,gg^M
pxy,aa,,cc,
40
,dd^M
所以然后使用任何awk:
$ awk -v ORS= '{sub(/\r$/,"\n")} 1' test.csv
234,aa,bb,cc,30,dd
22,cc,ff,dd,40,gg
pxy,aa,,cc,40,dd
或者,如果您愿意,可以将 GNU awk 用于多字符 RS:
$ awk -v RS='\r\n' '{gsub(/\n/,"")} 1' test.csv
234,aa,bb,cc,30,dd
22,cc,ff,dd,40,gg
pxy,aa,,cc,40,dd
有关使用 awk 解析 CSV 的更多信息,请参阅使用 awk 有效解析 CSV 的最可靠方法是什么?.
关于您的原始脚本 - 永远不要使用printf $0
,总是使用,printf "%s", $0
因为前者在$0
包含任何 printf 格式化字符时会失败,例如%s
:
$ echo 'a%sb' | awk '{printf "%s", $0}'
a%sb$
$ echo 'a%sb' | awk '{printf $0}'
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: not enough arguments to satisfy format string
`a%sb'
^ ran out for this one
$
这适用printf
于所有输入数据。