Regex Perl正则表达式压缩多个换行符

Regex Perl正则表达式压缩多个换行符,regex,perl,Regex,Perl,我似乎无法理解正确的语法,但我希望Perl正则表达式能够找到一行中有两个或更多换行符的位置,并将它们压缩为两个换行符 以下是我今天使用的似乎不起作用的东西: $string =~ s/\n\n+/\n\n/g; 请让我知道我做错了什么,以及我应该使用的正确Perl正则表达式 提前感谢您的帮助 展示一个完整的例子。什么是$string $ perl -E'my $s = qq{a\n\n\nb}; say "[$s]"; $s =~ s/\n\n+/\n\n/g; say "[$s]"' [a

我似乎无法理解正确的语法,但我希望Perl正则表达式能够找到一行中有两个或更多换行符的位置,并将它们压缩为两个换行符

以下是我今天使用的似乎不起作用的东西:

$string =~ s/\n\n+/\n\n/g;
请让我知道我做错了什么,以及我应该使用的正确Perl正则表达式


提前感谢您的帮助

展示一个完整的例子。什么是
$string

$ perl -E'my $s = qq{a\n\n\nb}; say "[$s]"; $s =~ s/\n\n+/\n\n/g; say "[$s]"'
[a


b]
[a

b]

@B真是一针见血。我做了一个快速测试用例:

中的

a

b




c
使用此代码:

my $line = join '', <>;
$line =~ s{\n\n+}{\n\n}g;
print $line;
通过更改记录分隔符(并避免使用正则表达式),可以获得相同的结果:

{
#将记录分隔符从“\n”更改为“”
#将多个换行符视为一个(perldoc perlvar)
#本地将对全局$/的更改限制在此块中
本地$/=”;
印刷品;
}
这样做:

#!/usr/bin/env perl
use strict;
use warnings;
my $string;
{
   local $/=undef;
   $string =<DATA>;
} 
print "Before:\n$string\n============";

$string=~s/\n{2,}/\n\n/g;
print "After:\n$string\n\nBye Bye!";

__DATA__
Line 1
Line 2






Line 9
Line 10

Line 12



Line 16


Line 19

Perl还支持
\R
字符类以实现平台独立性。您的正则表达式将是
s/\R{2,}/\n\n/g

如果您使用的是Perl 5.10或更高版本,请尝试以下操作:

$string =~ s/(\R)(?:\h*\R)+/$1$1/g;
\R
是通用的行分隔符转义序列(),
\h
匹配任何水平空白字符(例如空格和制表符)()。因此,这将把一个或多个空行的任意序列转换为一个空行

现在的大多数应用程序都很自由,它们将其视为行分隔符;他们甚至可以在同一个文档中混合使用两种或多种分隔符样式。另一方面,一些应用程序会主动将所有行分隔符转换为一种首选样式。但有时你必须坚持一种特定的风格;这就是为什么我捕获了第一个
\R
匹配项并将其用作替换项,而不是任意使用
\n


请注意,这些特殊的转义序列在其他正则表达式风格中不受广泛支持。它们在PHP的最新版本中工作,
\R
似乎在Ruby 2.0中工作,尽管我找不到任何提到它的文档。Ruby 1.9.2和2.0支持转义序列,但它匹配的是十六进制数字(
[0-9a-fA-F]
),而不是水平空格。在大多数其他风格中,
\R
\h
将抛出异常或分别匹配文本
R
h

您编写的正则表达式是正确的(以可能的行结尾问题为模),但关键在于如何调用它。你是不是一下子就把整个文件都弄脏了?还是你一行一行去?如果是后者,那么你的问题是,你永远不会一次将所有的行都放在一个字符串中。@b我会把整个文件都给它。我甚至通过搜索和替换来确认换行符之间没有其他字符,我已经确认它不起作用。你能想到其他的可能性吗?你在什么平台上如果在Windows上使用二进制模式,你会在每次
\n
之前得到
\r
。如果他们在那里,你需要对他们做出解释。此外,空行上可能有一些空格。@justintime:如果使用
\R
(?>\R\n |[\R\n])
的快捷方式,则平台与此无关。此答案已添加到“转义序列”下的。
#!/usr/bin/env perl
use strict;
use warnings;
my $string;
{
   local $/=undef;
   $string =<DATA>;
} 
print "Before:\n$string\n============";

$string=~s/\n{2,}/\n\n/g;
print "After:\n$string\n\nBye Bye!";

__DATA__
Line 1
Line 2






Line 9
Line 10

Line 12



Line 16


Line 19
Before:
Line 1
Line 2






Line 9
Line 10

Line 12



Line 16


Line 19
============After:
Line 1
Line 2

Line 9
Line 10

Line 12

Line 16

Line 19
$string =~ s/(\R)(?:\h*\R)+/$1$1/g;