应该在正则表达式中转义哪些文字字符?

Posted

技术标签:

【中文标题】应该在正则表达式中转义哪些文字字符?【英文标题】: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 【参考方案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);
?>

【讨论】:

以上是关于应该在正则表达式中转义哪些文字字符?的主要内容,如果未能解决你的问题,请参考以下文章

在 MySQL 中转义用户输入正则表达式的最佳方法是啥?

在正则表达式中转义特殊字符

如何在 oracle 中转义特殊的正则表达式字符?

需要在正则表达式中转义的所有特殊字符的列表

你如何在 Freemarker 中转义正则表达式字符串

在正则表达式中转义(\')单引号,它在两个单引号之间采用字符串。