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

4

我似乎无法找到正确的语法,但我想要一个Perl正则表达式来查找连续两个或更多换行符,并将它们压缩为只有2个换行符。

这是我今天使用的代码,但似乎不起作用:

$string =~ s/\n\n+/\n\n/g;

请告诉我我做错了什么,以及应该使用哪个正确的Perl正则表达式。

提前感谢您的帮助!


2
你写的正则表达式是正确的(除了可能存在行尾问题),但关键在于你如何调用它。你是一次性读入整个文件吗?还是逐行读取?如果是后者,那么你的问题就是你从未将所有行都存储在一个字符串中。 - btilly
@btilly - 我已经将整个文件都提供了。我甚至通过搜索和替换来确保在换行符之间没有其他字符,并确认它仍然无法工作。您还能想到其他可能性吗? - Russell C.
你用的是哪个平台? - justintime
1
如果在Windows上并且使用二进制模式,每个\n之前都会有\r。如果存在这些字符,您需要考虑它们。此外,空行上可能会有一些空格。 - bvr
1
@justintime:如果你使用\R(?>\r\n|[\r\n])的快捷方式),平台是不相关的。 - the wolf
4个回答

8
如果您正在使用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 支持 \h 转义序列,但它匹配一个十六进制数字 ([0-9a-fA-F]),而不是水平空白。在大多数其他版本中,\R\h 将抛出异常或分别匹配字面值 Rh


该答案已添加到Stack Overflow正则表达式FAQ,在“转义序列”下。 - aliteralmind

2

这就做到了:

#!/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

Perl还支持\R字符类以实现跨平台兼容性。请参见此SO链接。您的正则表达式将是s/\R{2,}/\n\n/g;


0
@btilly说得一点也没错。我进行了一个快速测试案例:

in

a

b




c

使用以下代码:

my $line = join '', <>;
$line =~ s{\n\n+}{\n\n}g;
print $line;

它返回了预期的结果:

a

b

c

通过更改记录分隔符(并避免使用正则表达式),您可以获得相同的结果:

{
    # change the Record Separator from "\n" to ""
    # treats multiple newlines as just one (perldoc perlvar)
    # local limits the change to the global $/ to this block
    local $/ = "";
    print <>;
}

0
展示一个完整的例子。什么是$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]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接