Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Regex Search String in a Variable

by roho (Chancellor)
on May 01, 2021 at 16:39 UTC ( #11131931=perlquestion: print w/replies, xml ) Need Help??

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

I am trying to replace part of a text string using a regular expression.

When I put the search string directly in the regular expression, it works (the text string is modified).

When I put the search string in a variable, it does not work (the text string is not modified).
Note: I tried running the search string variable through the "qr" function, but that did not help.

I feel like I am missing something very basic here, but I just can't see it. TIA for any suggestions.

#!/usr/bin/perl use strict; use warnings; my ($text, $search); $text = "\\x1\\x2\\x3\\x4"; print "\nUsing literal in regex: (success)\n"; print "Before: text = $text\n"; $text =~ s/x2\\.+\\x4/new/; print " After: text = $text\n"; $text = "\\x1\\x2\\x3\\x4"; $search = "x2\\.+\\x4"; print "\nUsing variable in regex: (failure)\n"; print "Before: text = $text\n"; $text =~ s/$search/new/; print " After: text = $text\n";

"It's not how hard you work, it's how much you get done."

Replies are listed 'Best First'.
Re: Regex Search String in a Variable
by LanX (Cardinal) on May 01, 2021 at 17:46 UTC
    Hi

    > I feel like I am missing something very basic here, but I just can't see it. TIA for any suggestions.

    You are getting bitten by what is called "slasheritis" in the emacs-lisp world.

    You have to escape backslashes from two interpretations which turns many elisp regexes into an unreadable mess filled with quadruple backslashes \\\\

    This works:

    #!/usr/bin/perl use strict; use warnings; use Test::More; my ($text, $search); $text = "\\x1\\x2\\x3\\x4"; $text =~ s/x2\\.+\\x4/new/; my $exp = $text; $text = "\\x1\\x2\\x3\\x4"; $search = "x2\\\\.+\\\\x4"; $text =~ s/$search/new/; my $got = $text; is( $got, $exp, "slasheritis"); done_testing;

    ok 1 - slasheritis 1..1

    there are more elegant solutions in Perl°, but I wanted to clarify the problem.

    HTH! :)

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

    °) alas not in GnuEmacs. XEmacs had "raw strings", but became abandon-ware.

      °) alas not in GnuEmacs. XEmacs had "raw strings", but became abandon-ware.

      While it does not provide raw strings, I've always found the rx macro to offer a very neat solution for building complicated regular expressions, somewhat akin to Perl's /x flag:

      (rx "\\x2" (one-or-more nonl) "\\x4")
        that's true, but you still need two \\ to quote a meta.

        here a bad but not exceptional line taken from cperl-mode

        "\\((\\(\\\\.\\|[^\\\\()]\\|([^\\\\()]*)\\)*)\\)?"

        edit

        and more things need escaping in elisp regexes

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

      Thanks LanX. You're right. Once I doubled the "double" backslashes it worked fine.

      "It's not how hard you work, it's how much you get done."

Re: Regex Search String in a Variable
by Discipulus (Abbot) on May 01, 2021 at 17:07 UTC
    Hello roho,

    > Note: I tried running the search string variable through the "qr" function, but that did not help.

    qr helps

    #!/usr/bin/perl use strict; use warnings; my ($text, $search); $text = "\\x1\\x2\\x3\\x4"; $search = qr/x2\\.+\\x4/; print "\nUsing variable in regex: (qr)\n"; print "Before: text = $text\n"; $text =~ s/$search/new/; print " After: text = $text\n"; __END__ Using variable in regex: (qr) Before: text = \x1\x2\x3\x4 After: text = \x1\new

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      Thanks Discipulus. I now see the reason my qr didn't work. It was because I first assigned the search string to the variable, then reassigned the variable (run through qr) to itself, which did not double the backslashes.

      my $search = "x2\\.+\\x4"; $search = qr($search);

      "It's not how hard you work, it's how much you get done."

Re: Regex Search String in a Variable
by AnomalousMonk (Bishop) on May 01, 2021 at 21:24 UTC

    You seem to understand this already, but I thought I'd try to make it clear for future readers of this thread: Why doesn't it work?

    When you finish slashing away at the $search string, what have you got?

    Win8 Strawberry 5.8.9.5 (32) Sat 05/01/2021 17:03:44 C:\@Work\Perl\monks >perl -Mstrict -Mwarnings -l my $search = "x2\\.+\\x4"; print $search; ^Z x2\.+\x4 ^^ || ++----- backslash escaped literal period (one or more)
    Unescaped, the . (dot) is a regex matching operator (see perlre, perlretut). Escaped, it matches a literal period, and there is no period to match in your example $text string. The + quantifier matches one or more of the atom before it, a literal period in this case.

    Similar result if you pass the $search string through the qr// regex object constructor.

    Win8 Strawberry 5.8.9.5 (32) Sat 05/01/2021 17:14:10 C:\@Work\Perl\monks >perl -Mstrict -Mwarnings -l my $search = "x2\\.+\\x4"; my $rx_search = qr/$search/; print $rx_search; ^Z (?-xism:x2\.+\x4)

    Update: Minor re-formatting for clarity/coherence.


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

      I think the easiest way to put it, is that backslash is the escape character for literal strings as well as for regex meta-characters.

      This means they need to be doubled for each step.

      Even in single quoted strings, since they allow escaping the delimiter.

      AFAIK are here-docs the only way to avoid the need of self-escaping a \

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

        AFAIK are here-docs the only way to avoid the need of self-escaping a \

        Actually, I was not aware of this, but yeah:

        Win8 Strawberry 5.8.9.5 (32) Sun 05/02/2021 21:06:46 C:\@Work\Perl\monks >perl -Mstrict -Mwarnings my $s = <<'EOT'; \b\\o\\\f\\\\f\ EOT print "'$s' \n"; $s = q/\q\\u\\\u\\\\x\ /; print "'$s' \n"; ^Z '\b\\o\\\f\\\\f\ ' '\q\u\\u\\x\ '
        Learned something today! :)


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

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11131931]
Approved by Discipulus
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2021-05-11 04:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Perl 7 will be out ...





    Results (113 votes). Check out past polls.

    Notices?