使用tr替换单个新行,但不能替换多个新行

时间:2016-04-12 16:44:28

标签: linux bash tr

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

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

但这会用|替换所有新行所以单独的产品不再是不同的产品线。我基本上想要一个|产品编号,标题和网址之间的分隔符,但每个单独的产品在不同的行上。我怎样才能做到这一点?

6 个答案:

答案 0 :(得分:1)

使用tr和一点sed:

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

答案 1 :(得分:0)

您可以使用awk执行此操作:

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

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

答案 2 :(得分:0)

已经部分回答了HERE,但并未完全回答。

我会添加一个额外的转换来将双换行符更改为某个字符(在本例中为hash),然后在更改单个行后用换行符替换哈希值(如果要返回原始格式,则替换为两行)新行是管道。

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

答案 3 :(得分:0)

awk救援!

awk -F'\n' -v RS= -v OFS='|' '{$1=$1;printf "%s", $0 RT}' file

这样可以保留段落间距,原始文件中的3行。

答案 4 :(得分:0)

只需使用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的第二个表达式用换行符替换尾随管道以产生更可读的输出(或更多&#34;常规&#34;文件末尾的空行)。

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

答案 5 :(得分:0)

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

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

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