以下为什么不将多个空行替换为一个?
$ 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
答案 0 :(得分:6)
之所以不起作用,是因为-p
告诉perl逐行处理输入,并且一行中的\n
不得超过一个。
更好的主意:
perl -00 -lpe 1
-00
:启用段落模式(输入记录由2条以上的换行符终止)。-l
:启用自动选择模式(输入记录分隔符会自动修剪,因此由于我们处于段落模式,因此所有尾随的换行符都将被删除,并且输出记录会添加"\n\n"
)。-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' | ...
将使用这些解决方案产生两个尾随空格。这可能是问题,也可能不是问题。