Bash 将与图案匹配的线移动到上一行

Bash 将与图案匹配的线移动到上一行,bash,sed,awk,vim,Bash,Sed,Awk,Vim,我有一个有结构的文件 12312 desc: bleh... 9938 desc: blah... desc: bloh... desc: blih... desc: bluh... 9912 desc: blah... 我想将匹配模式“desc:”的行移到前一行,或者删除每个模式“desc:”前面的行中的“\n” 期望输出: 12312 desc: bleh... 9938 desc: blah... desc: bloh... desc: blih... desc: bluh... 99

我有一个有结构的文件

12312
desc: bleh...
9938
desc: blah...
desc: bloh...
desc: blih...
desc: bluh...
9912
desc: blah...

我想将匹配模式“desc:”的行移到前一行,或者删除每个模式“desc:”前面的行中的“\n”

期望输出:

12312 desc: bleh...
9938 desc: blah... desc: bloh... desc: blih... desc: bluh... 
9912 desc: blah...
我试过了

awk '!/desc:/{
 printf "%s ",$0
 getline
 printf "%s \n",$0
}
/desc/{print}' file
没有结果

实际上,所有数据都是
awk-F\“{print$4”\t“$6}”的输出。

也许我可以先做点什么?

awk
单程:

$ awk '!/^desc:/&&NR>1{print OFS}{printf "%s ",$0}END{print OFS}' file
12312 desc: bleh...
9938 desc: blah... desc: bloh... desc: blih... desc: bluh...
9912 desc: blah...
说明:

  • !/^desc:///code>匹配不以
    desc:
    开头的行,不包括文件
    NR>1
    中的第一行
  • {print of s}
    在匹配行之前打印一个输出字段分隔符。在
    awk
    中,OFS
    的默认值为
    \n
  • {printf“%s”,$0}
    打印每一行,不带尾随换行符
  • END{print of s}
    读取文件后添加一个尾随换行符
实时演示:

Perl解决方案:

perl -pe 's/\n/ /; ! /^desc:/ and print "\n" unless 1 == $.' FILE

sed
oneliner

sed ':a $!N;s/\ndesc/ desc/;ta P;D'
将输出

12312 desc: bleh...
9938 desc: blah... desc: bloh... desc: blih... desc: bluh...
9912 desc: blah...
使用

script.vim的内容

set backup
g/\v^desc/ normal kJ
saveas! output.txt
q!
像这样运行:

vim -u NONE -N -S script.vim infile
它将创建一个包含以下内容的
output.txt
文件:

12312 desc: bleh...
9938 desc: blah...  desc: bloh...  desc: blih...  desc: bluh...
9912 desc: blah...
使用“新”GNU选项
-z
,您可以使用

| sed -z 's/\ndesc:/ desc:/g'

无法获取它:
desc:blah…
不匹配
9912
,但它会移动到它。您能澄清您的问题吗?我想将与模式“desc:”匹配的行移动到上一行,或删除每个模式“desc:”之前的行中的“\n”:“。使用getline通常是错误的方法,在这种情况下确实如此。在阅读并完全理解所有注意事项之前,不要考虑使用getline。你不能解释一下吗。我不相信同样的结果。实际上,所有数据都是
awk-F\“{print$4”\t“$6}”
@IgorVoltaic的输出。我已经添加了一个解释。数据来自何处并不重要,只要它是问题中描述的格式就行。说你没有得到相同的结果没有帮助。
结束{print of s}
将在每行末尾添加一个空格,使用
end{print”“}
仅打印一个换行符。您还可以使用
printf“%s”,而不是
printf“%s”,在每行末尾添加第二个空格“,$0
但您需要重新考虑脚本逻辑来解决这个问题。@Jaypal-这是处理连接行的常见awk方法。您可能需要在每行之前打印一个ORS(如果它是输入中的第一行,则不打印任何内容)或OFS,这取决于它是块中的第一行还是后续行,因此您只需使用三元表达式来捕获区分块中第一行和后续行的条件。True,只是在
printf
内部使用
三元运算符
非常好。如果1==$,使用
print“\n”不是更直观吗/^描述:/
?我想是
/^desc:/并打印“\n”,除非1==$。
表示
如果找不到desc,则打印换行,除非行上只有一个字段
。这是一个相当令人讨厌的陈述,因为它至少包含了一些负面因素。难道没有更清晰的方式来写吗?我看到建议打印“\n”,除非1==$。||/^desc://
在注释中,但是如果($.>1 | |//^desc:/)在perl中打印“\n”,您就不能写一些清晰而简单的东西吗?我甚至不知道这是否正确解释了最初的perl意图。好吧,这说明了我是如何做到这一点的:我从
开始,注意到开头的空行,所以添加了
,除非
| sed -z 's/\ndesc:/ desc:/g'