Sed 命令产生不需要的新行

Sed 命令产生不需要的新行

我的源文件只有 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.txtsed -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-whitespacenot来删除字段中的侧翼空格,如果您的输入实际上有标题,则删除空格。catmlr-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回忆捕获组匹配的内容)。

相关内容