Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

jonasbn (1153)

jonasbn
  reversethis-{gro.napc} {ta} {nbsanoj}
http://e-diot.dk/
AOL IM: BJonasN (Add Buddy, Send Message)

Perl Programmer located in Copenhagen, Denmark. Active member of Copenhagen Perl Mongers.

Author of:

  • Business::DK::CPR
  • Business::DK::CVR
  • Business::DK::PO
  • Business::OnlinePayment::CashCow
  • Date::Holidays
  • Date::Holidays::Abstract
  • Date::Holidays::Super
  • Date::Pregnancy
  • Games::Bingo
  • Games::Bingo::Bot
  • Games::Bingo::Print
  • Module::Info::File
  • Module::Template::Setup
  • Test::Timer

and maintainer of:

  • Tie::Tools
  • XML::Conf
  • Workflow

Journal of jonasbn (1153)

Tuesday May 18, 2004
01:50 AM

Perl Bug?

[ #18801 ]

Yesterday my friend Allan mailed me a script, he could not understand did not work for me to have a look at.

After debugging using the Perl debugger, trying all kind of tricks and reading some documentation, I started to suspect a bug in Perl, when I later talked to him, he had made an even smaller version of the and he mailed it to me.

I ended up writing my own barebones version of the demo, which demonstrates the problem:

use strict;
 
my $str = q(
J:somestring
I:someother
);
 
my $i = 0;
my $err = "\t### ERR ###\n\tNo match\n";
my $success = "\tsuccess...\n";
 
foreach my $key ("J","I") {
    my $str2 = $str;
 
    print "### RUN 1/".++$i." ###\nTesting \$str ... looking for $key\n";
    if ($str =~ m/^$key:.+/gm) {
        print "$success\n";
    } else {
        print "$err\n";
    }
 
    print "Testing \$str2 ... looking for $key\n";
    if ($str2 =~ m/^$key:.+/gm) {
        print "$success\n";
    } else {
        print "$err\n";
    }
}
 
foreach my $key ("I","J") {
    my $str2 = $str;
 
    print "### RUN 2/".++$i." ###\nTesting \$str ... looking for $key\n";
    if ($str =~ m/^$key:.+/gm) {
        print "$success\n";
    } else {
        print "$err\n";
    }
 
    print "Testing \$str2 ... looking for $key\n";
    if ($str2 =~ m/^$key:.+/gm) {
        print "$success\n";
    } else {
        print "$err\n";
    }
}

The problem see to be the /g operator in the regular expressions when it is removed the thing works and as the demo shows, when 'J' comes before 'I' there is no problem.

This is the output:

### RUN 1/1 ###
Testing $str ... looking for J
        success...
 
Testing $str2 ... looking for J
        success...
 
### RUN 1/2 ###
Testing $str ... looking for I
        success...
 
Testing $str2 ... looking for I
        success...
 
### RUN 2/3 ###
Testing $str ... looking for I
        ### ERR ###
        No match
 
Testing $str2 ... looking for I
        success...
 
### RUN 2/4 ###
Testing $str ... looking for J
        success...
 
Testing $str2 ... looking for J
        success...

If you alter the string so the part containing 'I' comes before the part that contains 'J', the problem is with 'J'.

I have searched for the string 'regex' at rt.perl.org only to be presented with 72 tickets. I have looking through some of these, but I have not yet found out whether this bug is already known.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • You reset $str2 (in essence) on every loop, but you continually match against the same $str.

    So if you unroll your loops, you get basically this.

    Look for, at the beginning of the string, "J:", followed by a bunch of stuff that isn't a newline. (.+ with /m). Did you succeed? Remember this spot and proceed.

    Look for, at the beginning of the string (where we left off), "I:", followed by a bunch of stuff that isn't a newline. Did you succeed? *Remember this spot and proceed*.

    Look for, at the beginning of
  • What Whammo [perl.org] said, and from perlop:

    In scalar context, each execution of "m//g" finds the next match, returning true if it matches, and false if there is no further match. The position after the last match can be read or set using the pos() function; see the pos entry in the perlfunc manpage. A failed match normally resets the search position to the beginning of the string, but you can avoid that by adding the "/c" modifier (e.g. "m//gc"). Modifying the target string also resets the search position.