我有一个如下格式的文本文件。第一行是“KEY”,第二行是“VALUE”。

KEY 4048:1736 string
3
KEY 0:1772 string
1
KEY 4192:1349 string
1
KEY 7329:2407 string
2
KEY 0:1774 string
1

我需要这个值和键在同一行。所以输出应该是这样的…

KEY 4048:1736 string 3
KEY 0:1772 string 1
KEY 4192:1349 string 1
KEY 7329:2407 string 2
KEY 0:1774 string 1

如果我可以使用一些分隔符,如$或:

KEY 4048:1736 string , 3

我如何将两条线合并成一条?


当前回答

如果Perl是一个选项,您可以尝试:

perl -0pe 's/(.*)\n(.*)\n/$1 $2\n/g' file.txt

其他回答

杀死一只狗的方法不止绞刑。[1]

awk '{key=$0; getline; print key ", " $0;}'

在引号内放入您喜欢的任何分隔符。


引用:

原本是“Plenty of ways to skin the cat”,后来变成了一个古老的、可能起源于宠物的表达,也和宠物无关。

awk:

awk 'NR%2{printf "%s ",$0;next;}1' yourFile

注意,在输出的末尾有一个空行。

sed:

sed 'N;s/\n/ /' yourFile
cat input.txt
KEY 4048:1736 string
3
KEY 0:1772 string
1
KEY 4192:1349 string
1
KEY 7329:2407 string
2
KEY 0:1774 string
1
paste -sd ' \n' input.txt
KEY 4048:1736 string 3
KEY 0:1772 string 1
KEY 4192:1349 string 1
KEY 7329:2407 string 2
KEY 0:1774 string 1
paste -sd ' \n' input.txt | rev | sed 's/ / , /' | rev
KEY 4048:1736 string , 3
KEY 0:1772 string , 1
KEY 4192:1349 string , 1
KEY 7329:2407 string , 2
KEY 0:1774 string , 1
perl -0pE 's{^KEY.*?\K\s+(\d+)$}{ $1}msg;' data.txt > data_merged-lines.txt

-0读取整个文件,而不是逐行读取; pE用循环包装代码并打印输出,详见http://perldoc.perl.org/perlrun.html; ^KEY匹配行首的“KEY”,后面是序列前任何(.*?)的非贪婪匹配

一个或多个空格\s+,包括换行符; 一个或多个数字(\d+),我们捕获并重新插入为$1;

后跟$的末尾。

\K方便地从替换中排除左边的所有内容,因此{$1}只替换1-2个序列,参见http://perldoc.perl.org/perlre.html。

与glenn jackman使用粘贴的回答略有不同:如果-d分隔符选项的值包含多个字符,则逐个粘贴这些字符,并结合-s选项在处理相同输入文件时继续这样做。

这意味着我们可以使用任何我们想要的分隔符加上转义序列\n来一次合并两行。

使用逗号:

$ paste -s -d ',\n' infile
KEY 4048:1736 string,3
KEY 0:1772 string,1
KEY 4192:1349 string,1
KEY 7329:2407 string,2
KEY 0:1774 string,1

还有美元符号:

$ paste -s -d '$\n' infile
KEY 4048:1736 string$3
KEY 0:1772 string$1
KEY 4192:1349 string$1
KEY 7329:2407 string$2
KEY 0:1774 string$1

它不能做的是使用由多个字符组成的分隔符。

作为奖励,如果粘贴是POSIX兼容的,这将不会修改文件中最后一行的换行符,因此对于具有奇数行数的输入文件,如

KEY 4048:1736 string
3
KEY 0:1772 string

粘贴不会在最后一行添加分隔字符:

$ paste -s -d ',\n' infile
KEY 4048:1736 string,3
KEY 0:1772 string