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

Hi, I'm having an annoying stupid and simple problem: I have a string equals to $str1 = "|L|D|"; and I want to know if string 2, $str2, is in $str1. I'm using the expression: if($str1 =~ /$str2/gi){... Why isn't it working? What am I doing wrong? This is stupid... Regards. Kepler

Replies are listed 'Best First'.
Re: Stupid question about strings...
by davido (Cardinal) on Jul 14, 2014 at 08:32 UTC

    The | character is a metacharacter, and if it exists in $str2, it is being interpreted as alternation. You probably want something like this:

    if( $str1 =~ m/\Q$str2/gi ) { ...

    Dave

      if( $str1 =~ m/\Q$str2/gi ) { ...

      The use of the  /g modifier is meaningless in this context, although it does no harm.

      Ok....I was being stupid..... Thank you very much for the help :) Kind regards, Kepler

        Not stupid. It's an easy mistake to make. By the way; I like the index option mentioned later in the thread better if your search string is just a string and not a pattern.


        Dave

Re: Stupid question about strings...
by RichardK (Parson) on Jul 14, 2014 at 10:22 UTC

    If you don't need any wildcards use index

    if (index($str1,$str2) != -1) { ... }

      Best, IMHO, because it is now quite obvious what “the programmer’s intent” must have been.   Anytime I see a regex, I know I’m going to have to “figure out” the regex in order to be certain what the code was meant to do, and I’m going to worry that the bug might actually be caused by some edge-case that the clever programmer didn’t anticipate.   If the same thing can be done with something that is simpler, it’s better.

Re: Stupid question about strings...
by SimonPratt (Friar) on Jul 14, 2014 at 08:33 UTC

    Hi, Kepler

    Try switching your variables in the comparison, ie if ( $str2 =~ /$str1/i ){...

    The other issue is that you have pipes at each end of $str1, which will probably interfere with the match (essentially allowing $str2 to always match), so you may want to do something about that (such as removing them, or escaping them, though that will also be problematic)

      C:\>perl -E "my $str1 = qq(|L|D|); my $str2 = qr(\|L\|);if ($str2 =~ $ +str1) { say 'foo';}" foo

      Actually, SimonPratt is right. From OP's description ($str2 ["is in"] as a part of $str1) requires a regex test (if used) in the above order.

      Update: Added direct quote from OP's spec to clarify my paraphase, "as a part of...."


      check Ln42!

        Nope. If you want to know if string2 is in string1, you need string1 on the left side and string2 on the right side of the binding operator.
        $ perl -E 'my $str1 = qq(one two three); my $str2 = qq(two); if ($str +2 =~ m/$str1/) { say "foo";}' $ perl -E 'my $str1 = qq(one two three); my $str2 = qq(two); if ($str +1 =~ m/$str2/) { say "foo";}' foo
        Your test is wrong for the following reason: if you want to try to put string1 on the right side, then it is string1 that should be a quotemetaed regex or have the pipes escaped:
        $ perl -E 'my $str1 = qr(\|L\|D\|); my $str2 = qq(\|L\|); if ($str2 = +~ m/$str1/) { say "foo";}' $ perl -E 'my $str1 = qq(\|L\|D\|); my $str2 = qr(\|L\|); if ($str1 = +~ m/$str2/) { say "foo";}' foo $ perl -E 'my $str1 = qq(|L|D|); my $str2 = qq(|L|); if ($str1 =~ m/\ +Q$str2/) { say "foo";}' foo
      if ( $str2 =~ /$str1/i ){...

      OP stated that the task is to find $str2 in $str1, so that's probably not right.

      such as ... escaping them, though that will also be problematic

      See davido's answer regarding \Q (as well as quotemeta).

        You're quite right, not sure what I was thinking!