http://qs321.pair.com?node_id=11139044

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

Hi Monks,
I wanted your help to fix a couple of pattern matching regex that I have. My script:
#!/usr/bin/perl use strict; use warnings; my $s='IIIIIIIIIIIIIIIIIIIIIIIIIIOOOOOSSSSS'; if (0 == $s =~ tr/[IOSM]//c) { print "case1\n"; } elsif (0 == $s =~ tr/[IOS]//c) { print "case2\n"; }

Can you tell me why it prints case1 although my string does not have M inside?

Replies are listed 'Best First'.
Re: Pattern matching regex problem
by jwkrahn (Abbot) on Nov 23, 2021 at 08:53 UTC

    You are NOT using "pattern matching regex", you are using transliteration.

     $s =~ tr/[IOSM]//c says to translate every character NOT in the list '[', 'I', 'O', 'S', 'M' or ']' to itself, and as a side effect return the count of characters modified.

    So the string in $s does not contain any characters that are not in the list '[', 'I', 'O', 'S', 'M' or ']'.

      Ok, I see the difference. So, how would I tell it to print 'case 1' if 'M' is present, and 'case 2' if it's not?

        If all you want to do is check the presence of M using tr/// then it is simple:

        #!/usr/bin/env perl use strict; use warnings; my $s='IIIIIIIIIIIIIIIIIIIIIIIIIIOOOOOSSSSS'; print "$s: " . ($s =~ tr/M/M/ ? "case1\n" : "case2\n"); $s .= 'M'; print "$s: " . ($s =~ tr/M/M/ ? "case1\n" : "case2\n");

        🦛

Re: Pattern matching regex problem
by Corion (Patriarch) on Nov 23, 2021 at 08:46 UTC

    tr doesn't take character classes in square brackets ([]), so your code can also be written as:

    if (0 == $s =~ tr/IOSM//c) {

    Your code counts whether there is any of the letters I, O, S or M in the string. Which is obviously true.

    Maybe you wanted to match the letters in order?

    m/I+O+S+M+/