不能用一个替换多个空行

时间:2018-09-22 22:14:46

标签: regex perl

以下为什么不将多个空行替换为一个?

$ cat some_random_text.txt  
foo   



bar   




test  

这不起作用:

$ cat some_random_text.txt | perl -pe "s/\n+/\n/g"
foo  



bar  





test  

我正在尝试将多行新行(即空行)替换为一条空新行,但是我使用的正则表达式无法正常工作,如您在示例代码段中所见。
我搞砸了吗?

预期结果是:

foo

bar

test

3 个答案:

答案 0 :(得分:6)

之所以不起作用,是因为-p告诉perl逐行处理输入,并且一行中的\n不得超过一个。

更好的主意:

perl -00 -lpe 1
  • -00:启用段落模式(输入记录由2条以上的换行符终止)。
  • -l:启用自动选择模式(输入记录分隔符会自动修剪,因此由于我们处于段落模式,因此所有尾随的换行符都将被删除,并且输出记录会添加"\n\n")。
  • li>
  • -p:启用自动输入/输出(对每个输入记录执行主代码; $_中剩下的任何内容都会自动打印)。
  • -e 1:使用不执行任何操作的虚拟主程序。

总而言之,除了将段落终止符标准化为恰好两个换行符之外,这无济于事。

答案 1 :(得分:2)

您正在执行以下程序:

LINE: while (<>) {
   s/\n+/\n/g;
}
continue {
   die "-p destination: $!\n" unless print $_;
}

由于您一次只能读取一行,并且由于一行是不是由换行符终止的换行符的字符序列,所以您的模式将永远不会匹配多个换行符。


简单的解决方法是告诉Perl将整个文件视为一行。另外,您不希望替换每个换行符,而只是替换两个或两个以上的换行符,并且希望用两个换行符替换该顺序。

perl -0777pe's/\n\n\K\n+//g; s^\n+//; s/\n\K\n\z//' some_random_text.txt

第二和第三次替换确保文件的开头和结尾没有空白行。


虽然将整个文件读入内存很容易,但这不是必需的。也可以通过维护一个标志来实现期望的输出,该标志指示上一行是否为空白。

perl -ne'if (/\S/) { print "\n" if $f; print; $f=0 } else { $f=1 }' some_random_text.txt

此解决方案还删除了文件开头和结尾的空白行。

答案 2 :(得分:2)

给出:

$ echo "$txt"
foo   



bar   




test  

您可以使用sed将空白行减少为单个\n

$ echo "$txt" | sed '/^$/N;/^\n$/D'
foo   

bar   

test  

更容易的是,您可以使用cat -s

$ echo "$txt" | cat -s            # same output 

perl中,惯用的1衬线是将-00用于段落模式:

$ echo "$txt" | perl -00pe0       # same output 

awk中,您可以通过设置RS=然后将ORS=设置为您希望替换\n的运行方式来使用段落模式:

$ echo "$txt" | awk '1' RS= ORS="\n\n"    # same output 

ikegami正确地指出printf 'a\n\n' | ...将使用这些解决方案产生两个尾随空格。这可能是问题,也可能不是问题。