Odd regular expression behaviour

J

Jon Combe

Can anyone explain why the following code is not doing what I expect
it to do ?

#!/usr/bin/perl -w

use strict;

my $inputDateFormat = "DD-MM-YY";

if ( $inputDateFormat =~ m/YY/g )
{
print "GOT YEAR \n";
}
print "ABOUT TO MATCH WITH [$inputDateFormat]\n";
if ( $inputDateFormat =~ m/MM/g )
{
print "GOT MONTH\n";
}

The output I get is

GOT YEAR
ABOUT TO MATCH WITH [DD-MM-YY]

I would expect it to also output "GOT MONTH"

With some expermentation I have found that removing the "g" modifier
from the end of the second match gives the correct result, but once
matched I want to use the "pos" function which seems to only work
correctly when you have the g modifier.

Oddly if I also do a match for DD:-

#!/usr/bin/perl -w

use strict;

my $inputDateFormat = "DD-MM-YY";

if ( $inputDateFormat =~ m/YY/g )
{
print "GOT YEAR \n";
}
print "ABOUT TO MATCH MONTH WITH [$inputDateFormat]\n";
if ( $inputDateFormat =~ m/MM/g )
{
print "GOT MONTH\n";
}
print "ABOUT TO MATCH DAY WITH [$inputDateFormat]\n";
if ( $inputDateFormat =~ m/DD/g )
{
print "GOT DAY\n";
}

I get output

GOT YEAR
ABOUT TO MATCH MONTH WITH [DD-MM-YY]
ABOUT TO MATCH DAY WITH [DD-MM-YY]
GOT DAY

So it matches DD but still won't match MM.

I've tried on perl 5.8.0, 5.8.7 and 5.6.1 with identical results.

I'm not sure if this is a bug or some subtle behaviour of regular
expressions I'm not aware of, but it certainly seems odd to me.

Also if I don't do the check for "YY" first it then matches MM but
fails to match DD

Jon
 
M

Martijn Lievaart

Can anyone explain why the following code is not doing what I expect it
to do ?

#!/usr/bin/perl -w

use strict;

my $inputDateFormat = "DD-MM-YY";

if ( $inputDateFormat =~ m/YY/g )
{
print "GOT YEAR \n";
}
print "ABOUT TO MATCH WITH [$inputDateFormat]\n"; if ( $inputDateFormat
=~ m/MM/g )
{
print "GOT MONTH\n";
}

The output I get is

GOT YEAR
ABOUT TO MATCH WITH [DD-MM-YY]

I would expect it to also output "GOT MONTH"

With some expermentation I have found that removing the "g" modifier
from the end of the second match gives the correct result, but once
matched I want to use the "pos" function which seems to only work
correctly when you have the g modifier.

Yes, /g starts from where the last match left. IIRC, reset pos to 0 to
avoid that and have a (better) look at perldoc perlre.

M4
 
J

John W. Krahn

Jon said:
Can anyone explain why the following code is not doing what I expect
it to do ?

#!/usr/bin/perl -w

use strict;

my $inputDateFormat = "DD-MM-YY";

if ( $inputDateFormat =~ m/YY/g )
{
print "GOT YEAR \n";
}
print "ABOUT TO MATCH WITH [$inputDateFormat]\n";
if ( $inputDateFormat =~ m/MM/g )
{
print "GOT MONTH\n";
}

The output I get is

GOT YEAR
ABOUT TO MATCH WITH [DD-MM-YY]

I would expect it to also output "GOT MONTH"

With some expermentation I have found that removing the "g" modifier
from the end of the second match gives the correct result, but once
matched I want to use the "pos" function which seems to only work
correctly when you have the g modifier.

Maybe you want to use index:

if ( ( $pos = index $inputDateFormat, 'YY' ) >= 0 )
{
print "GOT YEAR \n";
}
print "ABOUT TO MATCH WITH [$inputDateFormat]\n";
if ( ( $pos = index $inputDateFormat, 'MM' ) >= 0 )
{
print "GOT MONTH\n";
}



John
 
E

Eric Pozharski

Can anyone explain why the following code is not doing what I expect
it to do ?

#!/usr/bin/perl -w

use strict;

my $inputDateFormat = "DD-MM-YY";

if ( $inputDateFormat =~ m/YY/g )
{
print "GOT YEAR \n";
}
print "ABOUT TO MATCH WITH [$inputDateFormat]\n";
if ( $inputDateFormat =~ m/MM/g )
{
print "GOT MONTH\n";
}

The output I get is

GOT YEAR
ABOUT TO MATCH WITH [DD-MM-YY]

I would expect it to also output "GOT MONTH"

With some expermentation I have found that removing the "g" modifier
from the end of the second match gives the correct result, but once
matched I want to use the "pos" function which seems to only work
correctly when you have the g modifier.

Evaluate C<m//> in list context:

perl -wle '
$x = q|abc|;
print $y if $y = $x =~ m/c/g;
print $y if $y = $x =~ m/b/g;'
1

While:

perl -wle '
$x = q|abc|;
print $y if $y = () = $x =~ m/c/g;
print $y if $y = () = $x =~ m/b/g;'
1
1

*CUT*
 
J

Jon Combe

Yes, /g starts from where the last match left. IIRC, reset pos to 0 to
avoid that and have a (better) look at perldoc perlre.

OK thanks for the explanation. The problem is the "perlre" document
for the version of Perl I'm using makes no mention of the g modifier
at all. The only mention I can find is in the pos document itself. I
see that online versions of the document do mention this behaviour,
but it is not mentioned in the documentation for any of the versions
of Perl I have available.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top