如何从命令行将每两行合并为一行?

sha*_*nuo 137 bash awk grep sed

我有一个文本文件,格式如下.第一行是"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
Run Code Online (Sandbox Code Playgroud)

我需要与键相同的行中的值.所以输出应该是这样的......

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
Run Code Online (Sandbox Code Playgroud)

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

KEY 4048:1736 string , 3
Run Code Online (Sandbox Code Playgroud)

如何将两行合并为一行?

gle*_*man 220

paste 对这项工作有好处:

paste -d " "  - - < filename
Run Code Online (Sandbox Code Playgroud)

  • 关于参数的描述将是一个很好的补充 (11认同)
  • 这是有效的,因为“paste”总是从*每个输入文件*中获取一行,并输出一行,这些行由用“-d”定义的分隔符组合而成。这里的技巧是列出魔术输入文件“-”两次。按照 GNU 传统,文件名“-”表示从标准输入读取,并为“粘贴”列出该魔术文件两次,意味着它将从“第一个”输入文件读取一行,然后从“第二个”输入文件读取一行,总共 2 个从标准输入读取的行。然后,这些行将被连接起来,中间有一个空格。请注意,“-d”仅占用一个字节。 (11认同)
  • 我认为这是最好的解决方案,尽管既不使用sed也不使用awk.在奇数行的输入上,Kent的awk解决方案跳过最后的换行符,他的sed解决方案跳过其最后一行,我的解决方案重复了最后一行.另一方面,"粘贴"表现得非常完美.+1. (8认同)
  • 我经常使用`cut`但总是忘记`paste`.它解决了这个问题.我需要组合来自stdin的*all*行,并使用`paste -sd'' - `轻松完成. (7认同)
  • 所以`-`表示stdin,所以`paste - -`意味着从stdin读取,然后从stdin读取,你可以按照你的预期堆叠尽可能多的. (7认同)
  • 简单而美丽! (4认同)

Ken*_*ent 169

AWK:

awk 'NR%2{printf "%s ",$0;next;}1' yourFile
Run Code Online (Sandbox Code Playgroud)

请注意,输出结尾处有一个空行.

SED:

sed 'N;s/\n/ /' yourFile
Run Code Online (Sandbox Code Playgroud)

  • 因为谷歌真的很难,闭幕式后的"1"是什么意思? (9认同)
  • 如果在`$ 0`中找到``s s`这样的`printf`扩展字符串,这个awk解决方案可能会破坏.可以像这样避免这种失败:''NR%2 {printf"%s",$ 0; next;} 1'` (7认同)
  • @ erikb85在这里你去http://stackoverflow.com/questions/24643240/what-does-a-number-do-after-curly-braces (5认同)

nno*_*nog 34

替代sed,awk,grep:

xargs -n2 -d'\n'
Run Code Online (Sandbox Code Playgroud)

当你想加入N行并且只需要空格分隔输出时,这是最好的.

我原来的答案是xargs -n2单词而不是单词.-d可用于按任何单个字符拆分输入.

  • 这是一个很好的方法,但它适用于单词,而不是行.为了使它在线上工作,可以添加`-d'\n'` (3认同)
  • 哇,我是xargs的普通用户,但不知道这一点。大提示。 (2认同)
  • 我喜欢这个。那么干净。 (2认同)

gho*_*oti 26

杀死狗的方法多于悬挂的方法.[1]

awk '{key=$0; getline; print key ", " $0;}'
Run Code Online (Sandbox Code Playgroud)

在引号内放置你喜欢的任何分隔符.


参考文献:

  1. 最初"有很多方法可以给猫皮肤",它恢复了一种较老的,可能起源的表达,与宠物无关.

  • 作为猫主人,我不喜欢这种幽默. (4认同)
  • @ witkacy26,根据您的关注调整表达式. (4认同)

Hai*_* Vu 11

这是我在bash中的解决方案:

while read line1; do read line2; echo "$line1, $line2"; done < data.txt
Run Code Online (Sandbox Code Playgroud)


J.D*_*.D. 11

虽然看起来先前的解决方案可行,但如果文档中出现单个异常,则输出将变为碎片.下面有点安全.

sed -n '/KEY/{
N
s/\n/ /p
}' somefile.txt
Run Code Online (Sandbox Code Playgroud)

  • 为什么它更安全?`/ KEY /`做什么?`p`到底做了什么? (3认同)

jay*_*ngh 11

这是另一种方式awk:

awk 'ORS=NR%2?FS:RS' file
Run Code Online (Sandbox Code Playgroud)

$ cat file
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
Run Code Online (Sandbox Code Playgroud)

$ awk 'ORS=NR%2?FS:RS' file
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
Run Code Online (Sandbox Code Playgroud)

正如Ed Morton在评论中指出的那样,最好为安全性和便携性添加括号.

awk '{ ORS = (NR%2 ? FS : RS) } 1' file
Run Code Online (Sandbox Code Playgroud)

ORS代表输出记录分隔符.我们在这里做的是使用NR存储行号的条件来测试条件.如果模数为NR真值(> 0),那么我们将输出字段分隔符设置为FS(字段分隔符)的值,默认情况下为空格,否则我们分配RS(记录分隔符)的值为换行符.

如果您希望添加,为分隔符,请使用以下内容:

awk '{ ORS = (NR%2 ? "," : RS) } 1' file
Run Code Online (Sandbox Code Playgroud)


Jus*_*tin 7

"ex"是一个可编写脚本的行编辑器,与sed,awk,grep等属于同一个族.我认为它可能就是你要找的东西.许多现代vi克隆/后继者也有vi模式.

 ex -c "%g/KEY/j" -c "wq" data.txt
Run Code Online (Sandbox Code Playgroud)

这说的每一行,如果"KEY"匹配执行Ĵ OIN以下行的.该命令完成(对所有线)后,发出W¯¯仪式和q UIT.


anu*_*ava 5

您可以像这样使用 awk 来组合两对行:

awk '{ if (NR%2 != 0) line=$0; else {printf("%s %s\n", line, $0); line="";} } \
     END {if (length(line)) print line;}' flle
Run Code Online (Sandbox Code Playgroud)


and*_*efs 5

如果可以选择 Perl,您可以尝试:

perl -0pe 's/(.*)\n(.*)\n/$1 $2\n/g' file.txt
Run Code Online (Sandbox Code Playgroud)


Jen*_*sen 5

另一个使用 vim 的解决方案(仅供参考)。

解决方案1

在 vim 中打开文件vim filename,然后执行命令:% normal Jj

这个命令很容易理解:

  • % :对于所有行,
  • 正常:执行正常命令
  • Jj : 执行 Join 命令,然后跳转到下面一行

之后,保存文件并退出 :wq

解决方案2

在 shell 中执行命令vim -c ":% normal Jj" filename,然后保存文件并退出:wq


Ben*_* W. 5

glenn jackman 的答案略有不同,使用paste:如果-d分隔符选项的值包含多个字符,则一个一个地paste循环遍历这些字符,并结合-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
Run Code Online (Sandbox Code Playgroud)

和美元符号:

$ 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
Run Code Online (Sandbox Code Playgroud)

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

作为奖励,如果paste符合 POSIX,这不会修改文件中最后一行的换行符,因此对于具有奇数行的输入文件,例如

KEY 4048:1736 string
3
KEY 0:1772 string
Run Code Online (Sandbox Code Playgroud)

paste 不会在最后一行添加分隔符:

$ paste -s -d ',\n' infile
KEY 4048:1736 string,3
KEY 0:1772 string
Run Code Online (Sandbox Code Playgroud)