开发者

cant get the perl regex to work

My perl is getting rusty. It only prints "matched=" but $1 is blank!?!

EDIT 1: WHo the h#$! downvoted this? There are no wrong questions. If you dont like it, move on to next one!

$c开发者_运维问答razy="abcd\r\nallo\nXYZ\n\n\nQQQ";
if ($crazy =~ m/([.\n\r]+)/gsi) {
    print "matched=", $1, "\n";
} else {
    print "not matched!\n";
} 

EDIT 2: This is the code fragment with updated regex, works great!

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

EDIT 3: Haha, i see perl police strikes yet again!!!


I don't know if this is your exact problem, but inside square brackets, '.' is just looking for a period. I didn't see a period in the input, so I wondered which you meant.

Aside from the period, the rest of the character class is looking for consecutive whitespace. And as you didn't use the multiline switch, you've got newlines being counted as whitespace (and any character), but no indication to scan beyond the first record separator. But because of the way that you print it out, it also gives some indication that you meant more than the literal period, as mentioned above.


Axeman is correct; your problem is that . in a character class doesn't do what you expect.

By default, . outside a character class (and not backslashed) matches any character but a newline. If you want to include newlines, you specify the /s flag (which you seem to already have) on your regex or put the . in a (?s:...) group:

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


. in a character class is a literal period, not match anything. What you really want is /(.+)/s. The /g flag says to match multiple times, but you are using the regex in scalar context, so it will only match the first item. The /i flag makes the regex case insensitive, but there are no characters with case in your regex. The \s flag makes . match newlines, and it always matches "\r", so instead of [.\n\r], you can just use ..

However, /(.+)/s will match any string with one or more characters, so you would be better off with

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

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

It is possible you meant to do something like this:

#!/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";
}

But that would probably be better phrased:

#!/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";
}


$1 contains white space, that's why you don't see it in a print like that, just add something after it/quote it.

Example:

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

Updated for your comments:

To match everything you can simply use /(.+)/s


[.] (dot inside a character class) does not mean "match any character", it just means match the literal . character. So in an input string without any dots,

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

will just match strings of \n and \r characters. With the /s modifier, you are already asking the regex engine to include newlines with . (match any character), so you could just write

m/(.+)/gsi
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜