【问题标题】:What literal characters should be escaped in a regex?应该在正则表达式中转义哪些文字字符?
【发布时间】:2011-07-25 22:33:56
【问题描述】:

我刚刚编写了一个正则表达式,用于 php 函数 preg_match,其中包含以下部分:

[\w-.]

匹配任何单词字符,以及减号和点。虽然它似乎在 preg_match 中工作,但我尝试将它放入一个名为 Reggy 的实用程序中,它抱怨 “char 类中的空范围”。反复试验告诉我,这个问题是通过转义减号,将正则表达式变成

来解决的
[\w\-.]

既然原来的似乎在 PHP 中工作,我想知道为什么我应该或不应该转义减号,并且 - 因为点也是 PHP 中具有含义的字符 - 为什么我不需要转义点。我正在使用的实用程序是不是很傻,它是在使用另一种正则表达式方言还是我的正则表达式真的不正确?我只是幸运 preg_match 让我侥幸逃脱了吗?

【问题讨论】:

  • 有什么理由不使用preg_quote
  • 可能不会。但这不是我问这个问题的原因。我试图学习一些关于正则表达式的新知识,只是使用preg_quote 会产生完全相反的效果。 :)。我确实意识到我标记了这个 PHP,但我正在寻找一个可能适用于任何 PCRE 实现的答案。
  • 我明白了。那么,我可以建议:github.com/php/php-src/blob/…
  • 虽然它仍然没有“直接”告诉我什么和什么不应该逃避,以及为什么,但它确实提供了关于它的行为方式的所有答案。供参考,官方出处镜像:github.com/luvit/pcre2/tree/master/src

标签: php regex escaping pcre


【解决方案1】:

虽然确实有some characters should be escaped in a regex,但您问的不是正则表达式,而是字符类。其中破折号是特殊的。

你可以把它放在课堂结束时,而不是逃避它,[\w.-]

【讨论】:

    【解决方案2】:
    [\w.-]
    
    • . 通常表示任何字符,但[] 之间没有特殊含义
    • -[] 之间表示一个范围,除非它被转义或者[] 之间的第一个或最后一个字符

    【讨论】:

    • 在字符类中. 真的意味着“任何字符”吗? (即在括号之间)
    • @Pelle 这是真的。我只是在编辑答案。大多数答案都错了;-)
    【解决方案3】:

    句号在字符类中失去其元意义。

    - 在字符类中具有特殊含义。如果它没有放在方括号的开头或结尾,则必须对其进行转义。否则它表示一个字符范围(A-Z)。

    您触发了另一个特殊情况[\w-.] 有效,因为\w 不表示单个字符。因此,PCRE 不可能创建字符范围。 \w 可能是不连贯的符号类,因此没有可用于创建范围 Z till . 的结束字符。同样,句号. 将在\w 可以匹配的第一个ascii 字符a 之前。没有可构造的范围。因此- 工作而不为你逃跑。

    【讨论】:

      【解决方案4】:

      在许多正则表达式实现中,适用以下规则:

      字符类中的元字符是:

      • ^(否定)
      • -(范围)
      • ](课程结束)
      • \(转义字符)

      所以这些都应该被转义。不过也有一些极端情况:

      • - 如果放在类的开头或结尾([abc-][-abc]),则无需转义。在相当多的正则表达式实现中,当直接放置在范围 ([a-c-abc]) 或简写字符类 ([\w-abc]) 之后也不需要转义。这是你观察到的
      • ^ 在类的开头 not 时不需要转义:[^a] 表示除 a 之外的任何字符,[a^] 匹配 a^,等于:[\^a]
      • ] 如果是类中唯一的字符,则无需转义:[]] 匹配字符 ]

      【讨论】:

      • 非常全面的答案,谢谢。关于[]]的一个问题:如果你的班级只有一个角色,为什么不指定为\]? (即不在括号内)
      • @Pelle “为什么不”是另一个问题,无关紧要。 “有不止一种方法可以做到这一点”是 preg 发明者的座右铭;)
      • @Pelle,谢谢。没错,您可以(或应该?)简单地使用\] 而不是字符类,但我想提一下,许多正则表达式实现允许[]] 匹配文字]。你甚至不需要转义],因为它只是字符类中的一个元字符。在它之外,只有[ 需要从两个方括号中转义(但转义] 没有坏处!)。
      • 用于包装/分隔正则表达式的字符必须进行转义,通常是'/'。
      • @AFAMed,这是一种语言限制,并非特定于正则表达式本身。
      【解决方案5】:

      如果您使用 php 并且需要转义特殊的正则表达式字符,请使用 preg_quote:

      来自php.net的例子:

      <?php
      // In this example, preg_quote($word) is used to keep the
      // asterisks from having special meaning to the regular
      // expression.
      
      $textbody = "This book is *very* difficult to find.";
      $word = "*very*";
      $textbody = preg_replace ("/" . preg_quote($word, '/') . "/",
                                "<i>" . $word . "</i>",
                                $textbody);
      ?>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-12
        相关资源
        最近更新 更多