in reply to Unescaped left brace in regex is passed through in regex

You say ... the application is large and escape is a terrible job.

Well, how many separate source code files are there that make up the application? How many of them yield that sort error message when you run  perl -Tcw on each file? Among the affected files, how many lines of code actually cause that error message?

The error messages are "machine-readable" -- they report the line numbers and the affected strings in a consistent way. If it turns out that there are hundreds of lines to fix, you'll probably notice that they fall into a smaller number of patterns, and you can write a perl script to read the error messages and update the affected lines of the affected files -- saving the updated code in a separate directory, of course, so that you can run diff on the pre- and post-edited versions to confirm that all and only the intended changes have been made. (If there are just a few dozen lines to fix, stop complaining and just fix them.)

Replies are listed 'Best First'.
Re^2: Unescaped left brace in regex is passed through in regex
by gzh (Initiate) on Jun 06, 2022 at 07:56 UTC
    Dear graff

    Thank you very much for your suggestions.
    We found that not every regex with brace has an error.
    The real range may not be so large.

     if ($str =~ /(\\x{[A-F\d]+})/i){    // error by perl -Tcw
     if ($str =~ /^(\d{2,4})[^\d](\d{2})/){     // no error by perl -Tcw
      your code section is hard to decipher in my chrome

      >

      if ($str =~ /(\\x{[A-F\d]+})/i){ // error by perl -Tcw if ($str =~ /^(\d{2,4})[^\d](\d{2})/){ // no error by perl -Tcw

      some remarks:

      1. you don't append comments with // in Perl, it's #
      2. the no error part is legal syntax for a a range of repetitions
      3. the error part is not, hence (old) Perl thinks ° a literal curly { is expected. so implicitly { is translated to \{ instead of throwing an error
      4. the deprecation means that literal { has to be escaped explicitly now

      Please note the difference:

      (debugger demo with perl -de0 )

      DB<4> $str = '\\x{A3f4}' # +literal curly DB<5> if ( $str =~ /(\\x{[A-F\d]+})/i ) { print $1 } # +implicit but deprecated \x{A3f4} DB<6> use warnings; if ( $str =~ /(\\x\{[A-F\d]+})/i ) { print $1 } # +explicit and no warning \x{A3f4} DB<7> $str = '123X12' # +no curlies, just repeated numbers DB<8> if ( $str =~ /^(\d{2,4})[^\d](\d{2})/) { print "$1;$2" } # +meta curly 123;12

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

      °) see DWIM

        I try to follow what LanX does with the REPL. I'm confused right now.

        $ perl -de1 Loading DB routines from perl5db.pl version 1.53 Editor support available. Enter h or 'h h' for help, or 'man perldebug' for more help. main::(-e:1): 1 DB<1> $str = '\\x{A3f4}' + DB<2> p $str + \x{A3f4}

        Ok, so we begin the game with a string that has 2 backslashes before an x and then curly braces containing a value. We ask the debugger to print the value, and the output differs from the original string by having one fewer backslash.

        Q1) What makes you think this is a left-curly brace? I don't doubt you; I just can't get there:

        DB<2> print $str + \x{A3f4} DB<3> print "$str" + \x{A3f4}

        Q2) What is \x{value} called? I'm going up a wall trying to disambiguate it. I think it's completely-different from my \x experience with it in a regex: perlre#/x-and-/xx. Continuing:

        DB<3> if ( $str =~ /(\\x{[A-F\d]+})/i ) { print $1 } + Unescaped left brace in regex is deprecated here (and will be fatal in + Perl 5.30), passed through in regex; marked by <-- HERE in m/(\\x{ < +-- HERE [A-F\d]+})/ at (eval 13)[/usr/share/perl/5.28/perl5db.pl:738] + line 2.

        Ok, let's stop here. When I'm debugging my stuff, I typically think that the first error message is the one I need to attend to. What follows was the stack of things that bombed out because of the first error. This is as clear as an error message is, except that I'm not quite sure where it stops and the next one begins. Let's take a look at the rest of the message:

        at (eval 13)[/usr/share/perl/5.28/perl5db.pl:738] line 2. eval 'no strict; ($@, $!, $^E, $,, $/, $\\, $^W) = @DB::saved;pack +age main; $^D = $^D | $DB::db_stop; if ( $str =~ /(\\\\x{[A-F\\d]+})/i ) { print $1 }; ' called at /usr/share/perl/5.28/perl5db.pl line 738 DB::eval called at /usr/share/perl/5.28/perl5db.pl line 3138 DB::DB called at -e line 1 Unescaped left brace in regex is deprecated here (and will be fatal in + Perl 5.30), passed through in regex; marked by <-- HERE in m/(\\x{ < +-- HERE [A-F\d]+})/ at (eval 13)[/usr/share/perl/5.28/perl5db.pl:738] + line 2. at (eval 13)[/usr/share/perl/5.28/perl5db.pl:738] line 2. eval 'no strict; ($@, $!, $^E, $,, $/, $\\, $^W) = @DB::saved;pack +age main; $^D = $^D | $DB::db_stop; if ( $str =~ /(\\\\x{[A-F\\d]+})/i ) { print $1 }; ' called at /usr/share/perl/5.28/perl5db.pl line 738 DB::eval called at /usr/share/perl/5.28/perl5db.pl line 3138 DB::DB called at -e line 1 Unescaped left brace in regex is deprecated here (and will be fatal in + Perl 5.30), passed through in regex; marked by <-- HERE in m/(\\x{ < +-- HERE [A-F\d]+})/ at (eval 13)[/usr/share/perl/5.28/perl5db.pl:738] + line 2. at (eval 13)[/usr/share/perl/5.28/perl5db.pl:738] line 2. eval 'no strict; ($@, $!, $^E, $,, $/, $\\, $^W) = @DB::saved;pack +age main; $^D = $^D | $DB::db_stop; if ( $str =~ /(\\\\x{[A-F\\d]+})/i ) { print $1 }; ' called at /usr/share/perl/5.28/perl5db.pl line 738 DB::eval called at /usr/share/perl/5.28/perl5db.pl line 3138 DB::DB called at -e line 1 \x{A3f4}

        Can you "see" the layering of this, because I cannot. Q3) Is there a setting for the debugger that allows for more human readable error output, maybe a newline between layers?

        Q4) Why is any part of perl5db.pl asking itself this question:

        eval 'no strict; ($@, $!, $^E, $,, $/, $\\, $^W) = @DB::saved;package +main; $^D = $^D | $DB::db_stop; if ( $str =~ /(\\\\x{[A-F\\d]+})/i ) { print $1 };

        There are 4 backslashes before that x. I know this is a situation of garbage in, but how is this the garbage out?

        DB<5> $str = '123X12' + DB<6> p $str + 123X12 DB<7> if ( $str =~ /^(\d{2,4})[^\d](\d{2})/) { print "$1;$2" } + 123;12 DB<8> $str = '123{12' + DB<9> if ( $str =~ /^(\d{2,4})[^\d](\d{2})/) { print "$1;$2" } + 123;12

        Well, the rest of this makes sense to me, and it shows a use of the curly braces that I might know. I wouldn't understand it without working through it with the REPL. One final question:

        Q5) Is it said correctly that perl is written in c, but the perl debugger is written in perl?

        Gruss aus Amiland

      if ($str =~ /^(\d{2,4})[^\d](\d{2})/){     // no error by perl -Tcw

      Please note that in Perl regex syntax, \d{2,4} and \d{2} are counted quantifiers and are perfectly valid. This is very ancient and very common syntax, so let's hope it's never deprecated! (Pay no attention to the Raku behind the curtain.)


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

      The left curly brace is a meta-character only in certain contexts. Outside those contexts, old versions of Perl would accept them as literals even if they were not escaped. I believe the intent is to eventually require a literal curly braces but not meta-character curly braces to be escaped.

      In your first example. the left curly is a literal, and needs to be escaped. Looked at another way, the intent of the regex is to match something like "\x{deadbeef}".

      In your second example, the curly braces are meta-characters specifying numbers of characters to match: two to four digits followed by a non-digit followed by two digits. So no escape required, and in fact escaping the left curly brackets would break the regex functionally, though it would still compile.

      Maybe the error message is a bit unclear. It does not say "literal left curly," though that is probably implied by "is passed through ..."

      [OT] the first regexp can probably be written /(\\x\{[[:xdigit:]]})/, provided that is really your intent. Note, though, that \d matches any digit, not just ASCII digits. That is to say, your regexp will match "123\N{U+096A}" (a.k.a. ASCII one, ASCII two, ASCII three, Devanagari digit four), whereas mine will not. If you need to match non-ASCII digits, stay with your own regexp.

        WRT non-ASCII matching check perlre for the /a modifier (and friends) which can affect what classes match w/o changing the regex itself.

        The cake is a lie.
        The cake is a lie.
        The cake is a lie.