无法让perl正则表达式工作

时间:2011-07-07 18:23:06

标签: regex perl

我的perl生锈了。它只打印“匹配=”但是1美元是空白的!?!

编辑1:h#$!贬低这个?没有错误的问题。如果您不喜欢它,请转到下一个!

$crazy="abcd\r\nallo\nXYZ\n\n\nQQQ";
if ($crazy =~ m/([.\n\r]+)/gsi) {
    print "matched=", $1, "\n";
} else {
    print "not matched!\n";
} 

编辑2:这是更新的正则表达式的代码片段,效果很好!

$crazy="abcd\r\nallo\nXYZ\n\n\nQQQ";
if ($crazy =~ m/([\s\S]+)/gsi) {
    print "matched=", $1, "\n";
} else {
    print "not matched!\n";
} 

编辑3:哈哈,我看到perl警察再次罢工!!!

5 个答案:

答案 0 :(得分:5)

我不知道这是否是您的确切问题,但在方括号内,'.'只是寻找一段时间。我没有在输入中看到一段时间,所以我想知道你的意思。

除了句号,字符类的其余部分正在寻找连续的空格。由于您没有使用 m ultiline开关,因此您将新行计为空白(和任何字符),但没有指示扫描超出第一个记录分隔符。但是由于你打印它的方式,它也给出了一些迹象表明你的意思超过了文字时期,如上所述。

答案 1 :(得分:3)

Axeman是对的;你的问题是,角色类中的.没有达到预期的效果。

默认情况下,字符类外部的.(而不是反斜杠)与任何字符匹配,但与换行符匹配。如果您想要包含换行符,请在正则表达式中指定/ s标记(您似乎已经拥有)或将.放在(?s:...)组中:

my $crazy="abcd\r\nallo\nXYZ\n\n\nQQQ";
if ($crazy =~ m/((?s:.+))/) {
    print "matched=", $1, "\n";
} else {
    print "not matched!\n";
} 

答案 2 :(得分:2)

$1包含空格,这就是为什么你没有在那样的印刷品中看到它,只需在它之后添加一些东西/引用它。

示例:

perl -E "qq'abcd\r\nallo\nXYZ\n\n\nQQQ'=~/([.\n\r]+)/gsi;say 'got(',length($1),qq') >$1<';"
got(2) >
<

更新以征求您的意见:

要匹配所有内容,您只需使用/(.+)/s

即可

答案 3 :(得分:2)

字符类中的

.是文字句点,不匹配任何内容。你真正想要的是/(.+)/s/g标志表示要多次匹配,但您在标量上下文中使用正则表达式,因此它只匹配第一个项目。 /i标志使正则表达式不区分大小写,但正则表达式中没有包含大小写的字符。 \s标记使.与换行符匹配,并且始终与"\r"匹配,因此您可以使用[.\n\r]代替.

但是,/(.+)/s会匹配任何包含一个或多个字符的字符串,因此您最好使用

my $crazy="abcd\r\nallo\nXYZ\n\n\nQQQ";

if (length $crazy) {
    print "matched=$crazy\n";
} else {
    print "not matched!\n";
}

你可能想做这样的事情:

#!/usr/bin/perl

use strict;
use warnings;

my $crazy = "abcd\r\nallo\nXYZ\n\n\nQQQ";

while ($crazy =~ /(.+)[\r\n]+/g) {
    print "matched=$1\n";
}

但这可能会更好地表达:

#!/usr/bin/perl

use strict;
use warnings;

my $crazy = "abcd\r\nallo\nXYZ\n\n\nQQQ";

for my $part (split /[\r\n]+/, $crazy) {
    print "matched=$part\n";
}

答案 4 :(得分:1)

[.](字符类中的点)并不意味着“匹配任何字符”,它只是意味着匹配文字.字符。所以在没有任何点的输入字符串中,

m/([.\n\r]+)/gsi

只会匹配\n\r字符的字符串。 使用/s修饰符,您已经要求正则表达式引擎包含.的换行符(匹配任何字符),因此您只需编写

m/(.+)/gsi