我的源文件只有 6 行,但是当我使用 sed 命令应用文本限定符时,它为每个输入行创建 2 行。
源文件:
September 2022||2022|||13564|7JM9LF |DANIEL, PAPERMAN
September 2022||2022|||48917|7CX04Q |BROWN, RADY
September 2022||2022|||177456|75YBGL |LAYYNE, MAXWELL
September 2022||2022|||5326|774YMX |BROWN, WHITE
使用的命令:
sed 's/\([^|]*\)/\"&\"/g' ./src_mod.txt > tgt.txt
答案1
我猜测您正在尝试在所有|
定义的字段周围添加引号。您获得额外换行符的原因很可能是因为您有 Windows 样式的行结尾。
只需运行dos2unix src_mod.txt
或sed -i 's/\r//' src_mod.txt
.
以下是一些获得您想要的东西的其他方法,尽管我们的原始方法也应该有效:
$ sed -E 's/([^|]*)(\||$)/"\1"\2/g' file
"September 2022"|""|"2022"|""|""|"13564"|"7JM9LF "|"DANIEL, PAPERMAN"
"September 2022"|""|"2022"|""|""|"48917"|"7CX04Q "|"BROWN, RADY"
"September 2022"|""|"2022"|""|""|"177456"|"75YBGL "|"LAYYNE, MAXWELL"
"September 2022"|""|"2022"|""|""|"5326"|"774YMX "|"BROWN, WHITE"
或者,如果您无法使用-E
:
sed 's/\([^|]*\)\(|\|$\)/"\1"\2/g' file
或者perl:
$ perl -F'\|' -lane 'print join("|", map{ qq/"$_"/} @F)' file
"September 2022"|""|"2022"|""|""|"13564"|"7JM9LF "|"DANIEL, PAPERMAN"
"September 2022"|""|"2022"|""|""|"48917"|"7CX04Q "|"BROWN, RADY"
"September 2022"|""|"2022"|""|""|"177456"|"75YBGL "|"LAYYNE, MAXWELL"
"September 2022"|""|"2022"|""|""|"5326"|"774YMX "|"BROWN, WHITE"
或者perl:
$ perl -F'\|' -lane 'print "\"",join("\"|\"", @F), "\""' file
"September 2022"|""|"2022"|""|""|"13564"|"7JM9LF "|"DANIEL, PAPERMAN"
"September 2022"|""|"2022"|""|""|"48917"|"7CX04Q "|"BROWN, RADY"
"September 2022"|""|"2022"|""|""|"177456"|"75YBGL "|"LAYYNE, MAXWELL"
"September 2022"|""|"2022"|""|""|"5326"|"774YMX "|"BROWN, WHITE"
答案2
您的问题可能是您的输入文件不是 Unix 文本文件。它可能是 DOS 文本文件。
CSV 感知工具将忽略您的输入是 DOS 文本文件,从而允许您在本机适当地引用字段。
以下用于csvformat
引用所有以竖线分隔的字段。本练习的输入已转换为 DOS 文本文件:
$ csvformat -d '|' -D '|' -U1 file
"September 2022"|""|"2022"|""|""|"13564"|"7JM9LF "|"DANIEL, PAPERMAN"
"September 2022"|""|"2022"|""|""|"48917"|"7CX04Q "|"BROWN, RADY"
"September 2022"|""|"2022"|""|""|"177456"|"75YBGL "|"LAYYNE, MAXWELL"
"September 2022"|""|"2022"|""|""|"5326"|"774YMX "|"BROWN, WHITE"
csvformat
(部分csvkit) 默认情况下,仅引用实际需要引用的字段,因为如果将字段分隔符更改为默认逗号,则每个记录中的最后一个字段将需要引用:
$ csvformat -d '|' file
September 2022,,2022,,,13564,7JM9LF ,"DANIEL, PAPERMAN"
September 2022,,2022,,,48917,7CX04Q ,"BROWN, RADY"
September 2022,,2022,,,177456,75YBGL ,"LAYYNE, MAXWELL"
September 2022,,2022,,,5326,774YMX ,"BROWN, WHITE"
磨坊主是另一个支持 CSV 的工具:
$ mlr --csv --fs pipe -N --quote-all cat file
"September 2022"|""|"2022"|""|""|"13564"|"7JM9LF "|"DANIEL, PAPERMAN"
"September 2022"|""|"2022"|""|""|"48917"|"7CX04Q "|"BROWN, RADY"
"September 2022"|""|"2022"|""|""|"177456"|"75YBGL "|"LAYYNE, MAXWELL"
"September 2022"|""|"2022"|""|""|"5326"|"774YMX "|"BROWN, WHITE"
该工具也仅默认引用所需内容。
$ mlr --csv --ifs pipe -N cat file
September 2022,,2022,,,13564,7JM9LF ,"DANIEL, PAPERMAN"
September 2022,,2022,,,48917,7CX04Q ,"BROWN, RADY"
September 2022,,2022,,,177456,75YBGL ,"LAYYNE, MAXWELL"
September 2022,,2022,,,5326,774YMX ,"BROWN, WHITE"
在命令中使用clean-whitespace
not来删除字段中的侧翼空格,如果您的输入实际上有标题,则删除空格。cat
mlr
-N
答案3
sed
不这样做,除非您告诉它,否则它不会添加换行符。
在这里,您的输入文件很可能具有 MS-DOS CRLF 行结尾,因此从 Unix 角度来看(行以 LF 分隔),行显示为以 CR 字符结尾,因此在输出中您会得到以 结尾的行,|"CR"
并且出于某种原因您截取屏幕截图的应用程序也将 CR 渲染为行分隔符。
在这里,您希望将这些文件转换为 Unix 格式。dos2unix
是执行此操作的工具,但如果您没有它,您可以使用perl
两者来删除那些尾随的 CR 字符并在每个字段周围添加引号:
perl -lpe 's/\r$//; $_ = join "|", map qq("$_"), split /\|/, $_, -1' <src_mod.txt >tgt.txt
需要注意的是,空行被视为 0 个字段的列表,而不是包含一个空字段。
您还可以删除全部CR 字符,不仅仅是行尾的字符,tr
并用 进行替换sed
:
<src_mod.txt tr -d '\r' | sed 's/[^|]*/"&"/g' >tgt.txt
请注意,"
不应在替换中转义,并且无需使用\(...\)
捕获组,因为&
会回忆整个匹配的文本(您将用来\1
回忆捕获组匹配的内容)。