Perl 在shell命令行中将两个换行符替换为一个

Perl 在shell命令行中将两个换行符替换为一个,perl,shell,replace,sed,newline,Perl,Shell,Replace,Sed,Newline,关于将多个换行符替换为一个换行符,有很多问题,但没有人为我工作。 我有一个文件: first line second line MARKER third line MARKER other lines many other lines 我需要将标记之后的两个换行符(如果存在)替换为一个换行符。结果文件应为: first line second line MARKER third line MARKER other lines many other lines 我尝试了sed]:a;N、

关于将多个换行符替换为一个换行符,有很多问题,但没有人为我工作。
我有一个文件:

first line
second line MARKER

third line MARKER
other lines

many other lines
我需要将
标记
之后的两个换行符(如果存在)替换为一个换行符。结果文件应为:

first line
second line MARKER
third line MARKER
other lines

many other lines
我尝试了
sed]:a;N、 美元!文学士;s/MARKER\n\n/MARKER\n/g'
失败。
sed
对于单行替换很有用,但是换行有问题。它找不到
\n\n

我尝试了
perl-I-p-e's/MARKER\n\n/MARKER\n/g'
失败。
此解决方案看起来更接近,但似乎regexp对
\n\n
没有反应

是否可以仅在
标记之后替换
\n\n
,而不替换文件中的其他
\n\n

我对一行解决方案感兴趣,而不是脚本。

请参阅。

您的Perl解决方案不起作用,因为您正在搜索包含两个换行符的行。没有这样的事。这里有一个解决方案:

perl -ne'print if !$m || !/^$/; $m = /MARKER$/;' infile > outfile
或在适当的地方:

perl -i~ -ne'print if !$m || !/^$/; $m = /MARKER$/;' file
如果可以将整个文件加载到内存中,可以使用

perl -0777pe's/MARKER\n\n/MARKER\n/g;' infile > outfile

如上所述,您可以使用
-i~
就地编辑。如果不想备份,请删除
~

awk:

kent$  cat a
first line
second line MARKER

third line MARKER
other lines

many other lines

kent$  awk 'BEGIN{RS="\x034"} {gsub(/MARKER\n\n/,"MARKER\n");printf $0}' a
first line
second line MARKER
third line MARKER
other lines

many other lines

我认为你的思路是对的。在多行程序中,您可以将整个文件加载到单个标量中,并对其运行此替换:

s/MARKER\n\n/MARKER\n/g
让一行代码将文件加载到多行字符串中的诀窍是在
BEGIN
块中设置
$/
。在读取输入之前,此代码将执行一次

perl -i -pe 'BEGIN{$/=undef} s/MARKER\n\n/MARKER\n/g' input

这可以通过非常简单的
sed
完成

sed '/MARKER$/{n;/./!d}'

这可能适合您:

 sed '/MARKER/,//{//!d}'
说明:

删除
标记
之间的所有行,保留
标记

或:

说明:


阅读
标记
后的下一行,然后在该行后面追加该行。如果当前行是标记行,则删除前一行。

虽然这在理论上可以回答问题,但在此处包括答案的基本部分,并提供链接供参考。考虑到该链接中有大量不相关的单行程序,这一点尤其正确。我找不到一个解决这一特定问题的方法,通过搜索文档中的“新行”或“\n \n”,我希望通过这样的解决方案来提及。@ OLUCKYMAN,它不是空的,它只包含了应该删除的空行。我把病情逆转了。已修复。@oluckyman,对于每一行,1)如果当前行前面没有标记行(通过选中$m)或不是空的,则打印当前行。2)在$m中注意当前行是否为标记行。@ OLUKYMAN,第三版本:1)告诉Perl,考虑整个文件一行(<代码> -0777 < /代码>,然后2),对于每一行,2a)替换每个“\n”前面的“标记n”,没有任何内容,2b)打印出行。谢谢!池上的帖子比较早,但你的解决方案更清晰!这正是我所问的。@oluckyman,我故意避开这个答案,因为它不必要地将整个文件加载到内存中。但由于您似乎更喜欢较短的答案,我在我的答案中添加了一个更简洁的解决方案。
sed '/MARKER$/{n;/./!d}'
 sed '/MARKER/,//{//!d}'
sed '/MARKER/{n;N;//D}'