Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

If I have two variables, I wish to compare one to the other, the problem is that the fist variable will contain value "1.1.2" the second will be "1.1"

How do I test for a match within the first two digits? The first variable can be quite long, like 1.1.2.1 etc, but I only want to check that the first two digits are the same as the second variable, regardless of how many digits the first variable has.

thanks in advance

Replies are listed 'Best First'.
Re: Regex question
by Skeeve (Parson) on May 22, 2007 at 09:42 UTC

    If the second variable is always just 2 numbers seperated by a "." I'd suggest doing it this way:

     if ( "$var2." eq substr("$var1.", 0, 1+length $var2) ) { ... }

    Not a regex thou...

    Update at -2: Yes! It's not a regex. But: Why should one use a regex here where a simple string comparison will do?

    Could those downvoters please comment what they think is wrong with my solution except that I don't break a fly on the wheel.


    s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
    +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
      Very clever, adding a dot after the variables to make sure you do not get a false positive in case of partial matches!

      ++ wel deserved.

      CountZero

      "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Regex question
by BrowserUk (Patriarch) on May 22, 2007 at 09:57 UTC

    If you use a regex, you're going to have to quotemeta one of the strings because '.' is a meta (regex command) character.

    If you use substr, you'll have problems if the length of the part you are trying to match can vary. Ie. Could the strings be '13.2.3' & '13.2' for example.

    Using index will allow you to avoid both these problems. You simple want to know if the shorter string matches the longer string at position 0:

    $var1 = '1.1.2'; $var2 = '1.1'; if( index( $var1, $var2 ) == 0 ) { print "matches" } else { print "Doesn't match" }

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      This will never match and is completly wrong as you mixed up $var1 and $var2.

      It should be

      index( $var2, $var1 ) == 0

      but this will still be wrong because

      $var2='1.11.2'; $var1='1.1';

      would give you a false match


      s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
      +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
        This will never match and is completly wrong as you mixed up $var1 and $var2.

        Um, no.

        C:\parrot>p1 [0] Perl> $var1 = '1.1.2'; $var2 = '1.1'; if( index( $var1, $var2 ) == 0 ) { print "matches" } else { print "Doesn't match" };; matches [0] Perl> $var1 = '1.1.2'; $var2 = '1.1'; if( index( $var2, $var1 ) == 0 ) { print "matches" } else { print "Doesn't match" };; Doesn't match

        but this will still be wrong because

        $var2='1.11.2'; $var1='1.1';

        would give you a false match

        That's a good catch though. It's also easily fixed:

        [0] Perl> $var1 = '1.11.2'; $var2 = '1.1'; if( index( $var1, "$var2." ) == 0 ) { print "matches" } else { print "Doesn't match" };; Doesn't match

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Regex question
by fenLisesi (Priest) on May 22, 2007 at 13:15 UTC
    use strict; use warnings; my @dotted_stuff = ( q(), '1.A', '12.1', '1.9', '01.9', '1.9.1', '1.9.2.1', '12.1.1', '12.13', ); for my $va (@dotted_stuff) { for my $vb (@dotted_stuff) { printf qq(%-7s and %-7s => ), $va, $vb; if ($va =~ m{ \A (\d+) \. (\d+) }xms) { my ($a1, $a2) = ($1, $2); if ($vb =~ m{ \A (\d+) \. (\d+) }xms) { my ($b1, $b2) = ($1, $2); if ($a1 == $b1 and $a2 == $b2) { print "MATCH!\n"; next; } } } print "no match.\n"; } }
Re: Regex question
by robot_tourist (Hermit) on May 22, 2007 at 09:58 UTC

    If your second variable is always 3 characters and the first is always at least three characters, then it's not too hard, you could see if a substring of var1 eq var2. Or even the following works for me

    if ($var1 =~ /^$var2/) { print "matched"; }

    Or you could do character by character comparisons. I'm sure in this case there are many ways to do it, though it would get complicated if you wanted to do a compare where $var1 used periods and $var2 used underscores or something.

    UPDATE: 20070522 11:01 localtime > ++ to BrowserUK for index

    UPDATE: 20070522 11:57 localtime > got a pm (thought it was a reply) and can't remember who sent it now, but props to the monk in question for reminding me to anchor the regex with ^

    How can you feel when you're made of steel? I am made of steel. I am the Robot Tourist.
    Robot Tourist, by Ten Benson

Re: Regex question
by chrism01 (Friar) on May 23, 2007 at 06:15 UTC
    It's not clear what the OP means by "1st 2 digits":

    1. 1st 2 chars
    if( substr($v1, 0, 2) eq substr($v2, 0, 2) )
    2. 1st 3 chars where 2nd char is '.'
    if( (substr($v1, 0, 3) eq substr($v2, 0, 3) ) && substr($v1, 1 ,1) eq '.' && substr($v2, 1 ,1) eq '.' )
    3. 1st 3 chars where 2nd char is anything
    if( substr($v1, 0, 3) eq substr($v2, 0, 3) )
    Cheers
    Chris