in reply to Re: How can I test for the representation of an integer?
in thread How can I test for the representation of an integer?

Here's why - two regexps which return an array with the same result, but for different reasons

~$ perl -MData::Dumper -e 'print Dumper("1" =~ /1/)' $VAR1 = 1; ~$ perl -MData::Dumper -e 'print Dumper("1" =~ /(1)/)' $VAR1 = '1';

Replies are listed 'Best First'.
Re^3: How can I test for the representation of an integer?
by hippo (Archbishop) on Apr 25, 2016 at 10:24 UTC

    One is a match and the other is a count - you can tell that from the different ways you have constructed the regex. By choosing a confusing value to test against makes this less obvious. Instead try with "2":

    $ perl -MData::Dumper -e 'print Dumper("2" =~ /2/);' $VAR1 = 1; $ perl -MData::Dumper -e 'print Dumper("2" =~ /(2)/);' $VAR1 = '2';

      Hi hippo,

      I think you're thinking of s///g, since m// doesn't return a count (perlop):

      $ perl -MData::Dumper -e 'print Dumper( "abbbbc"=~/b/ )' $VAR1 = 1; $ perl -MData::Dumper -e 'print Dumper( "abbbbc"=~/(b)/ )' $VAR1 = 'b'; $ perl -MData::Dumper -e 'print Dumper(scalar("abbbbc"=~/b/ ))' $VAR1 = 1; $ perl -MData::Dumper -e 'print Dumper(scalar("abbbbc"=~/(b)/ ))' $VAR1 = 1; $ perl -MData::Dumper -e 'print Dumper(scalar("abbbbc"=~/b/g ))' $VAR1 = 1; $ perl -MData::Dumper -e 'print Dumper(scalar("abbbbc"=~/(b)/g))' $VAR1 = 1; $ perl -MData::Dumper -e 'print Dumper( "abbbbc"=~/b/g )' $VAR1 = 'b'; $VAR2 = 'b'; $VAR3 = 'b'; $VAR4 = 'b'; $ perl -MData::Dumper -e 'print Dumper( "abbbbc"=~/(b)/g )' $VAR1 = 'b'; $VAR2 = 'b'; $VAR3 = 'b'; $VAR4 = 'b';

      To get a count you need to use the =()= trick (perlsecret):

      $ perl -MData::Dumper -e 'print Dumper(scalar(()="abbbbc"=~/b/g))' $VAR1 = 4; $ perl -MData::Dumper -e 'print Dumper(scalar(()="abbbbc"=~/(b)/g))' $VAR1 = 4;

      Regards,
      -- Hauke D

      The regexps are user-supplied and arbitrary - they may or may not have captures.
      Matching the number '1' is a real use-case.

        So I guess you want the count rather than the match (since you didn't specify). In that case, just force scalar context:

        $ perl -MData::Dumper -e 'print Dumper(scalar ("2" =~ /(2)/));' $VAR1 = 1;

        Update: As per haukex's correction the scalar context simply forces true/false rather than the count of matches. The above strategy still applies if this (whether the regex is a match or not) is all that you really want to test.

Re^3: How can I test for the representation of an integer? (updated!)
by haukex (Archbishop) on Apr 25, 2016 at 10:23 UTC

    Hi sm@sh,

    I'm not quite sure I understand yet, could you provide some more context? Are you trying to determine whether a regex had capture groups or not? If so, how about this?

    "1" =~ /1/; print @->1?"yes\n":"no\n"; "1" =~ /(1)/; print @->1?"yes\n":"no\n"; __END__ no yes

    This uses the special variable @-, aka @LAST_MATCH_START.

    Update 2018-09-01: Actually, @+ will give you the number of capture groups! See my reply below for the difference.

    Regards,
    -- Hauke D

      Thanks - that's very interesting (@LAST_MATCH_START).
      Sorry I wasn't clear about the use case, but I'm now curious about the representation - I'm aware there are many ways to test the regexp status.
      I had been using $& to test for the general match state, but that can perform badly.

        If you want to know whether a regular expression matches, why not simply use the regular expression in boolean context? A regular expression can match a zero-width string, so testing $& won't always help. I would use something like the following:

        my $regexp = 'hello.*world'; if( /$regexp/ ) { print "Your regexp '$regexp' matches '$_'\n"; for my $match ( 0..$#- ) { print sprintf "Match %02d (%d, %d):\t[%s]\n", $match, $-[$matc +h], $+[$match], substr( $_, $-[$match], $+[$match] ); }; };

        But as you haven't told us what the overall problem is you're trying to solve, I might be wildly off the mark. Maybe read XY Problem and then restate the actual problem you're trying to solve. That might be easier to solve than removing the problem where your current approach becomes untractable.

        Hi sm@sh,

        "1"==1, "1" eq 1, and looks_like_number(1) and looks_like_number("1") are all true in Perl. The StackOverflow thread that clueless newbie linked to already contains some excellent answers - especially choroba and ikegami's answers explain the caveats of peeking under the hood. That's why I recommended looking for a different solution to your problem than figuring out difference between 1 and "1".

        Regards,
        -- Hauke D

        Are you trying to determine whether a regex had capture groups or not?
        Thanks - that's very interesting (@LAST_MATCH_START).

        Through some code I am currently working on I discovered a potential problem here, there is a subtle but very important distinction between @- and @+, from the former:

        One can use $#- to find the last matched subgroup in the last successful match. Contrast with $#+, the number of subgroups in the [last successful] regular expression.
        $ perl -MData::Dump -e '"ya"=~/(x)?/; dd $#-, \@-, $#+, \@+' (0, [0], 1, [0, undef])

        And updating my previous example:

        "1" =~ /1/ or die; print $#-?"yes\n":"no\n"; # -> no "1" =~ /(1)?/ or die; print $#-?"yes\n":"no\n"; # -> yes "1" =~ /(2)?/ or die; print $#-?"yes\n":"no\n"; # -> no !! "1" =~ /(2)?/ or die; print $#+?"yes\n":"no\n"; # -> yes