使用 tr 替换单个新行而不是多个新行

Use tr to replace single new lines but not multiple new lines

您好,我有一个包含以下格式数据的文件:

262353824192
Motley Crue Too Fast For Love Vinyl LP Leathur Records LR123 rare 3rd pressing
http://www.ebay.co.uk/itm/Motley-Crue-Too-Fast-Love-Vinyl-LP-Leathur-Records-LR123-rare-3rd-pressing-/262353824192



301870324112
TRAFFIC Same UK 1st press vinyl LP in gatefold / booklet sleeve Island pink eye
http://www.ebay.co.uk/itm/TRAFFIC-Same-UK-1st-press-vinyl-LP-gatefold-booklet-sleeve-Island-pink-eye-/301870324112



141948187203
NOW That's What I Call Music LP'S Joblot 2-14 MINT CONDITION Vinyl
http://www.ebay.co.uk/itm/NOW-Thats-Call-Music-LPS-Joblot-2-14-MINT-CONDITION-Vinyl-/141948187203

我想用管道替换单个新行,但让双新行保持原样。我试过:

tr '\n' '|' < text.txt

但这会将所有新行替换为 |因此,单独的产品不再位于不同的生产线上。我基本上想要一个 |产品编号、标题和 url 之间的分隔符,但每个单独的产品在不同的行上。我怎样才能做到这一点?

您可以使用 awk 来做到这一点:

awk ' /^$/ { print; } /./ { printf("%s|", [=10=]); } END {print '\n'}' text.txt

这将找到任何空白行并按原样打印。如果它鳍 ds 行上的任何值,它将使用 printf 并在其后粘贴一个管道。在处理结束时,它会打印一个换行符来结束。

这已经得到了部分回答HERE,但还没有完全回答。

我会添加一个额外的转换来将双换行符更改为某个字符(在本例中为散列),然后在更改后用换行符替换散列(或者两个,如果你想回到原来的格式)单个换行符是管道。

sed -e ':a' -e 'N' -e '$!ba' -e 's/\n\n/#/g' -e 's/\n/|/g' -e 's/#/\n/g'

这给出了输出:

262353824192|Motley Crue Too Fast For Love Vinyl LP Leathur Records LR123 rare 3rd pressing|http://www.ebay.co.uk/itm/Motley-Crue-Too-Fast-Love-Vinyl-LP-Leathur-Records-LR123-rare-3rd-pressing-/262353824192

301870324112|TRAFFIC Same UK 1st press vinyl LP in gatefold / booklet sleeve Island pink eye|http://www.ebay.co.uk/itm/TRAFFIC-Same-UK-1st-press-vinyl-LP-gatefold-booklet-sleeve-Island-pink-eye-/301870324112

141948187203|NOW That's What I Call Music LP'S Joblot 2-14 MINT CONDITION Vinyl|http://www.ebay.co.uk/itm/NOW-Thats-Call-Music-LPS-Joblot-2-14-MINT-CONDITION-Vinyl-/141948187203

awk 救援!

awk -F'\n' -v RS= -v OFS='|' '{=;printf "%s", [=10=] RT}' file

这保留了段落之间的间距,与原始文件中一样为 3 行。

只需使用 sed:

sergey@x50n:~> cat in.txt | tr '\n' '|' | sed -e 's/||\+/\n\n/g; s/|$/\n/'
262353824192|Motley Crue Too Fast For Love Vinyl LP Leathur Records LR123 rare 3rd pressing|http://www.ebay.co.uk/itm/Motley-Crue-Too-Fast-Love-Vinyl-LP-Leathur-Records-LR123-rare-3rd-pressing-/262353824192

301870324112|TRAFFIC Same UK 1st press vinyl LP in gatefold / booklet sleeve Island pink eye|http://www.ebay.co.uk/itm/TRAFFIC-Same-UK-1st-press-vinyl-LP-gatefold-booklet-sleeve-Island-pink-eye-/301870324112

141948187203|NOW That's What I Call Music LP'S Joblot 2-14 MINT CONDITION Vinyl|http://www.ebay.co.uk/itm/NOW-Thats-Call-Music-LPS-Joblot-2-14-MINT-CONDITION-Vinyl-/141948187203

首先,我们使用 tr 将所有换行符替换为管道,如您的示例所示。

然后 sed 命令中的第一个表达式(即 s/||\+/\n\n/g;)用两个换行符替换所有出现的多个管道。如果您不希望输出行之间有空行,您也可以将它们替换为一行。 sed 的第二个表达式用换行符替换尾部管道以产生更易读的输出(或文件末尾的更多 "conventional" 空行)。

另请注意,sed 正则表达式中的 \+ 是 GNU 扩展。因此,如果您使用 sed(FreeBSD、AIX 等)的非 GNU 实现,请使用标准语法:|||* 而不是 ||\+.

我用 awk 对你的问题做了一个非常具体的解决方案(具体是因为它假设你在记录组之间总是有相同数量的新行)。

awk 'BEGIN {RS="\n\n\n"; FS="\n"; OFS="|"} {print ,,}' < text.txt

设置记录分隔符为3个换行符,字段分隔符为1个换行符,输出字段分隔符为管道符。然后对于每条记录(每个块由 3 个换行符分隔),它打印前 3 个字段(由一个换行符分隔),并在输出中用竖线

分隔它们

使用 tr 和一点 sed:

tr "\n" "|" < text.txt | sed 's/||\+/\n/g'