in reply to regex issue

Bored:
my $number = '01'; while(<DATA>) { print if ( (/$number/ ... /^\d\d/) =~ /^\d(?!E0)/); } __DATA__ 01 - three cans - one file - three balls 02 - none - yes coffee 03 - foo - bar

Replies are listed 'Best First'.
Re: Re: regex issue
by Hofmator (Curate) on May 11, 2004 at 09:51 UTC
    My reading of the question is a bit different. Shouldn't that be      print if /$number/ ... /^\d+/ and /^-/; and thus not print out any number, just the lines starting with '-'?

    And as a little explanation of BUU's rather unusal construct (the 2nd half, not the '...' operator itself), a little excerpt from perlop:

    The value returned [by the '..'/'...' operator] is either the empty string for false, or a sequence number (beginning with 1) for true. The sequence number is reset for each range encountered. The final sequence number in a range has the string "E0" appended to it, which doesn't affect its numeric value, but gives you something to search for if you want to exclude the end-point.
    That is what is being tested for with /^\d(?!E0)/. It also becomes clear, that there is a subtle bug lurking here if there are 10 or more lines. To fix that, the regex has to read /^(?>\d+)(?!E0)/.

    -- Hofmator

Re: Re: regex issue
by Belgarion (Chaplain) on May 11, 2004 at 04:40 UTC

    BUU, could you explain what your code is doing? I've not seen a construct like this before, and so I have no idea how it works.

    Thank you for any enlightenment you can provide.

      You'll find information about "..." in perlop:

      In scalar context, ".." returns a boolean value. The operator is bistable, like a flip-flop...

      (I doubt I can explain this particular construct in any sort of coherent manner, so I'll leave that to BUU.)

        Basically the flip-flop operator has two sides, a left hand and a right hand. The left hand side is evaluated first, and it it returns false, the entire construct returns false. However, when the left side returns true, the entire construct returns true and *keeps* returning true untill the right hand side also returns true, then the entire thing starts to return false again. Heres an example in code:
        for(0..10) { if(/2/../5/) { print; } }
        On the first iteration, it checks /2/ against $_, which contains 0, so it returns false and nothing is printed. On the second iteration, same thing, except $_ contains 1. On the third iteration however, $_ contains 2 so /2/ matches and the construct returns true and it prints. It keeps printing numbers untill $_ matches /5/.

        The more verbose form of this code would look like:
        my $flag; for(0..10) { if(/2/) { $flag = 1; } print if $flag; if(/5/) { $flag = 0; } }
        Note that the check to set $flag to 0 is *after* the print statement. This is because the construct returns true the first time the right hand side also returns true. It of course returns false after that.

        For the rest of my original code, as hofmator explains below, (/foo/../bar/) returns a string, not just a boolean value, and that string has "E0" appended to it when the right hand returns true (thus meaning it's the last value the flip-flop will return true for).