在Perl正则表达式中不推荐使用左大括号 - 恰好在何时?

jm6*_*666 8 regex perl

perldoc perlre 这样说:

(如果大括号出现在任何其他上下文中并且不构成反斜杠序列的一部分\x{...},则将其视为常规字符.但是,对于所有此类事件都会引发弃用警告,而在Perl v5.26中,文字使用一个花括号的大概需要被转义,比如在它们前面用反斜杠("\{")或将它们括在方括号("[{]")中.这个改变将允许将来的语法扩展(比如使量词的下限可选),以及更好的量词错误检查.)

好的,所以下面打印了弃用消息.

perl -lE 'm/x{x}/'
Run Code Online (Sandbox Code Playgroud)

为什么不以下?

perl -lE 'm/x({x})/'
Run Code Online (Sandbox Code Playgroud)

例如在捕获组中是否{允许未转义?可能不是因为

perl -lE 'm/x(x{x})/'
Run Code Online (Sandbox Code Playgroud)

还打印警告.

那么,什么是确切的"逻辑"?

PS:我会逃避每一个文字{,但我想知道上面背后的理由.

Thi*_*Not 5

警告仅在卷曲时发出:

  • 不是模式的开头
  • 遵循字母字符
  • 不是的一部分特殊的转义序列 \b{},\B{},\g{},\k{},\N{},\o{},\p{},\P{},或者\x{}
  • 不是形式的量词的一部分{n},{n,}或者{n,m},其中,nm是正整数

请参阅Perl源代码中的regcomp.c(以下内容来自5.22.0):

        case '{':
            /* Currently we don't warn when the lbrace is at the start
             * of a construct.  This catches it in the middle of a
             * literal string, or when its the first thing after
             * something like "\b" */
            if (! SIZE_ONLY
                && (len || (p > RExC_start && isALPHA_A(*(p -1)))))
            {
                ckWARNregdep(p + 1, "Unescaped left brace in regex is deprecated, passed through");
            }
            /*FALLTHROUGH*/
        default:    /* A literal character */
          normal_default:
            if (UTF8_IS_START(*p) && UTF) {
                STRLEN numlen;
                ender = utf8n_to_uvchr((U8*)p, RExC_end - p,
                                       &numlen, UTF8_ALLOW_DEFAULT);
                p += numlen;
            }
            else
                ender = (U8) *p++;
            break;
        } /* End of switch on the literal */
Run Code Online (Sandbox Code Playgroud)

演示:

$ perl -e '/{/'    # Beginning of pattern, no warning

$ perl -e '/.{/'   # Doesn't follow alpha, no warning

$ perl -e '/x{3}/' # Valid quantifier, no warning

$ perl -e '/\x{/'  # Part of special escape sequence \x{}, different warning
Missing right brace on \x{} in regex; marked by <-- HERE in m/\x{ <-- HERE / at -e line 1.

$ perl -e '/x{/'   # Follows alpha, isn't a quantifier or special escape, warns
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/x{ <-- HERE / at -e line 1.
Run Code Online (Sandbox Code Playgroud)