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

I am reading data from a file then looking for this to occur in a different variable. If the data read from the file contains regular expression characters Perl tries to expand them before doing the comparison. This is an issue if the data file has something like "[A" in it since this then results in an unmatched [ in regex error. This can be simplified be removing the file reading and directly assigning as shown below... e.g.
$Name = "[A"; $SearchInHere = "FredJimBert"; if ($SearchInHere =~/$Name/) { DoSomething(); }
How do I stop the "[" in $Name from being interpreted as a regular expression control character? Remember... $Name is really read from a file so I can't escape it. I need to modify the search, not the source data. Regards, Steve

Replies are listed 'Best First'.
Re: Stop variable expansion
by choroba (Cardinal) on Mar 18, 2021 at 21:30 UTC
    If you want to search for a string, not a regex, use index.

    my $Name = '[A'; my $SearchInHere = 'FredJimBert'; if (-1 != index $SearchInHere, $Name) { DoSomething(); }

    > so I can't escape it.

    Of course you can. See quotemeta. But I still think using the above solution is better.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      Excellent. Index did the trick. I think indexing is the better solution than character replacement since I don't have to think about all possible characters that could cause issue, and it just does the comparison character by character regardless, which is really what I want in this case. Expanding the regular expression is also extremely useful and I use it a lot in other applications but thought I had to explicitly enable it (with eval) rather than explicitly disable it somehow. Anyhow. Thanks for the solution :) BR, Steve
        I think indexing is the better solution than character replacement ...

        index seems a very good match to your use-case.

        ... I don't have to think about all possible characters that could cause issue ...

        That's exactly what quotemeta (and its \Q...\E avatar) does for you: escape all characters that could possibly cause an issue.

        Expanding the regular expression is also extremely useful and I use it a lot in other applications but thought I had to explicitly enable it (with eval) rather than explicitly disable it somehow.

        I don't understand what this means. Are we still talking about meta-quotation? Could you give an example of what you're doing with eval? (Please see Short, Self-Contained, Correct Example.)


        Give a man a fish:  <%-{-{-{-<

      OK, so I didn't know how to replace the "rogue" characters with escaped versions, and looking at the solution there is no way I would have been able to work that one out !!! :) Indexing I think is the right solution and better matches the intent, i.e. find 'this' in 'that'. Thanks for taking the time to reply and help. Very much appreciated. BR, Steve
        looking at the solution there is no way I would have been able to work that one out

        Of course there was a way - RTFM: read the fine manual. In fact both answers gave you the reference you needed: quotemeta. One of Perl's good points is comprehensive documentation. Sometimes it takes some digging, and it's harder if you don't know what you are looking for, but it's almost always there.

        For future reference you can of course quote problematic strings (as already noted in earlier answers):

        use strict; use warnings; my $Name = '[A'; my $SearchInHere = "FredJimBert[A"; print "Matched quoted\n" if $SearchInHere =~/\Q$Name\E/; print "Matched raw\n" if $SearchInHere =~/$Name/;

        Prints:

        Unmatched [ in regex; marked by <-- HERE in m/[ <-- HERE A/ at noname. +pl line 8. Matched quoted

        Output order is backwards in time, but that's pretty normal for errors and warnings.

        Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
Re: Stop variable expansion
by haukex (Archbishop) on Mar 18, 2021 at 21:29 UTC

    $SearchInHere =~ /\Q$Name\E/, see also quotemeta

      Thanks for the quotemeta suggestion. I will play with this to better understand its behavior. Thanks for taking the time to help. Very much appreciated. BR, Steve