正则表达式中必须转义哪些特殊字符?

Posted

技术标签:

【中文标题】正则表达式中必须转义哪些特殊字符?【英文标题】:What special characters must be escaped in regular expressions? 【发布时间】:2018-03-02 02:37:00 【问题描述】:

我厌倦了总是试图猜测,在使用许多正则表达式实现时,是否应该转义特殊字符,如“()[]|”等。

与 Python、sed、grep、awk、Perl、rename、Apache、find 等不同。 是否有任何规则集告诉我什么时候应该,什么时候不应该转义特殊字符?它是否取决于正则表达式类型,例如 PCRE、POSIX 或扩展正则表达式?

【问题讨论】:

好的正则表达式库具有像“escape()”这样的函数,允许使用任意字符串作为正则表达式部分。 您可以使用在线正则表达式检查器,例如gskinner.com/RegExr(它是免费的)。 (输入,然后将鼠标悬停在您输入的正则表达式上) 转义所有非字母数字字符。期间。 此问题已添加到Stack Overflow Regular Expression FAQ 的“其他”下。 此问题已添加到Stack Overflow Regular Expression FAQ 的“转义序列”下。 【参考方案1】:

哪些字符必须转义,哪些字符不能转义,实际上取决于您使用的正则表达式风格。

对于 PCRE 和大多数其他所谓的 Perl 兼容风格,请转义这些外部字符类:

.^$*+?()[\|

以及这些内部字符类:

^-]\

对于 POSIX 扩展正则表达式 (ERE),转义这些外部字符类(与 PCRE 相同):

.^$*+?()[\|

转义任何其他字符是 POSIX ERE 的错误。

在字符类中,反斜杠是 POSIX 正则表达式中的文字字符。你不能用它来逃避任何事情。如果要将字符类元字符包含为文字,则必须使用“巧妙的放置”。将 ^ 放在除开头之外的任何位置,将 ] 放在开头,将 - 放在字符类的开头或结尾以匹配这些字面意思,例如:

[]^-]

在 POSIX 基本正则表达式 (BRE) 中,这些是您需要转义以抑制其含义的元字符:

.^$*[\

BRE 中的转义括号和大括号赋予它们在 ERE 中未转义版本的特殊含义。一些实现(例如 GNU)在转义时也会赋予其他字符特殊的含义,例如 \?和+。转义 .^$*() 以外的字符通常是 BRE 的错误。

在字符类中,BRE 遵循与 ERE 相同的规则。

如果这一切让您头晕目眩,请获取RegexBuddy 的副本。在“创建”选项卡上,单击“插入令牌”,然后单击“文字”。 RegexBuddy 将根据需要添加转义。

【讨论】:

在我看来你忘记了“/”,它也需要在类外转义。 / 在我提到的任何正则表达式风格中都不是元字符,因此正则表达式语法不需要转义它。当正则表达式在编程语言中被引用为文字时,该语言的字符串或正则表达式格式规则可能要求 /"' 被转义,甚至可能需要 `\`双重逃脱。 冒号“:”呢?是否应在字符类内部和外部进行转义? en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions 说“PCRE 具有一致的转义规则:任何非字母数字字符都可以转义以表示其文字值 [...]” 可以转义与应该转义不同。 PCRE 语法从不需要转义文字冒号,因此转义文字冒号只会使您的正则表达式更难阅读。 对于非 POSIX ERE(我最常使用的 ERE,因为它是由 Tcl 实现的)转义其他内容不会产生错误。【参考方案2】:

现代正则表达式 (PCRE)

包括 C、C++、Delphi、EditPad、Java、javascript、Perl、php (preg)、PostgreSQL、PowerGREP、PowerShell、Python、REALbasic、Real Studio、Ruby、TCL、VB.Net、VBScript、wxWidgets 、XML Schema、Xojo、XRegExp。PCRE 兼容性可能不同

    任何地方:. ^ $ * + - ? ( ) [ ] \ |


旧版正则表达式 (BRE/ERE)

包括 awk、ed、egrep、emacs、GNUlib、grep、PHP (ereg)、mysql、Oracle、R、sed。PCRE 支持可以在以后的版本中或通过使用扩展来启用

ERE/awk/egrep/emacs

    在字符类之外:. ^ $ * + ? ( ) [ \ | 字符类内部:^ - [ ]

BRE/ed/grep/sed

    在字符类之外:. ^ $ * [ \ 在字符类中:^ - [ ] 对于文字,不要转义:+ ? ( ) | 对于标准正则表达式行为,请转义:\+ \? \( \) \ \ \|


注意事项

如果不确定某个特定字符,可以像\xFF 一样对其进行转义 字母数字字符不能用反斜杠转义 在 PCRE 中可以使用反斜杠对任意符号进行转义,但在 BRE/ERE 中则不能(它们只能在需要时进行转义)。对于 PCRE ] - 只需要在字符类中转义,但为了简单起见,我将它们保存在一个列表中 带引号的表达式字符串还必须对周围的引号字符进行转义,并且通常带有双倍的反斜杠(例如 "(\")(/)(\\.)" 与 JavaScript 中的 /(")(\/)(\.)/) 除了转义之外,不同的正则表达式实现可能支持不同的修饰符、字符类、锚点、量词和其他功能。欲了解更多详情,请查看regular-expressions.info,或使用regex101.com 实时测试您的表达方式

【讨论】:

您的回答中有很多错误,包括但不限于:您的“现代”风格都不需要 -] 在字符类之外转义。 POSIX (BRE/ERE) 在字符类中没有转义字符。 Delphi 的 RTL 中的正则表达式风格实际上是基于 PCRE。 Python、Ruby 和 XML 有自己的风格,它们更接近于 PCRE 而不是 POSIX 风格。 @JanGoyvaerts 感谢您的更正。你提到的口味确实更接近PCRE。至于逃生,为了简单起见,我保持这种方式;到处逃跑比几个例外更容易记住。高级用户会知道发生了什么,如果他们想避免一些反斜杠。无论如何,我更新了我的答案,并做了一些澄清,希望能解决其中的一些问题。 我已经找了好几天了!你是最棒的! 你还需要在字符类中转义“\”吗? 还有单引号、双引号和“/”呢?如何在 BRE 和 ERE 语法中获取它们的字面值?【参考方案3】:

不幸的是,实际上并没有一组转义码,因为它会根据您使用的语言而有所不同。

但是,保留 Regular Expression Tools Page 或 Regular Expression Cheatsheet 之类的页面可以帮助您快速过滤掉内容。

【讨论】:

Addedbytes 备忘单过于简单化,并且有一些明显的错误。例如,它说 \<\> 是单词边界,这在 Boost 正则表达式库中是唯一的(AFAIK)。但在其他地方它说<> 是元字符,必须转义(到\<\>)才能匹配它们,这在任何情况下都不是真的【参考方案4】:

POSIX 可识别正则表达式的多种变体 - 基本正则表达式 (BRE) 和扩展正则表达式 (ERE)。即便如此,由于 POSIX 标准化的实用程序的历史实现也存在一些怪癖。

对于何时使用哪种表示法,甚至给定命令使用哪种表示法,没有一个简单的规则。

查看 Jeff Friedl 的 Mastering Regular Expressions 书籍。

【讨论】:

【参考方案5】:

不幸的是,像 ( 和 \( 之类的东西的含义在 Emacs 风格的正则表达式和大多数其他风格之间互换了。所以如果你试图逃避这些,你可能会做与你想要的相反的事情。

所以你真的必须知道你要引用什么风格。

【讨论】:

【参考方案6】:

真的,没有。大约有五亿种不同的正则表达式语法;总的来说,它们似乎归结为 Perl、EMACS/GNU 和 AT&T,但我也总是感到惊讶。

【讨论】:

【参考方案7】:

有时,您列出的字符无法进行简单的转义。例如,使用反斜杠转义括号在 sed 中的替换字符串的左侧不起作用,即

sed -e 's/foo\(bar/something_else/'

我倾向于只使用简单的字符类定义,所以上面的表达式变成了

sed -e 's/foo[(]bar/something_else/'

我发现它适用于大多数正则表达式实现。

顺便说一句,字符类是非常普通的正则表达式组件,因此它们往往适用于大多数需要在正则表达式中转义字符的情况。

编辑:在下面的评论之后,我想我会提到一个事实,即在查看正则表达式的行为时,您还必须考虑有限状态自动机和非有限状态自动机之间的区别评估。

您可能想看看“闪亮的球书”,即 Effective Perl (sanitised Amazon link),特别是关于正则表达式的章节,以了解正则表达式引擎评估类型的差异。

并非所有世界都是 PCRE!

无论如何,与SNOBOL 相比,正则表达式实在是太笨重了!现在是一门有趣的编程课程!连同Simula 上的那个。

70 年代末在新南威尔士大学学习的乐趣啊! (-:

【讨论】:

'sed' 是一个命令,普通的 '(' 并不特殊,但 '\(' 是特殊的;相反,PCRE 反转了意义,所以 '(' 是特殊的,但 '\( ' 不是。这正是 OP 所要求的。 sed 是一个 *nix 实用程序,它使用最原始的正则表达式评估集之一。 PCRE 没有进入我描述的情况,因为它涉及不同类别的(无限)有限自动机,它评估正则表达式的方式。我认为我对最小正则表达式语法集的建议仍然成立。 在符合 POSIX 的系统上,sed 使用 POSIX BRE,我在回答中对此进行了介绍。现代 Linux 系统上的 GNU 版本使用带有一些扩展的 POSIX BRE。【参考方案8】:

https://perldoc.perl.org/perlre.html#Quoting-metacharacters 和 https://perldoc.perl.org/functions/quotemeta.html

在官方文档中,这样的字符被称为元字符。引用示例:

my $regex = quotemeta($string)
s/$regex/something/

【讨论】:

【参考方案9】:

对于 PHP,“在非字母数字前面加上“\”来指定它代表自己总是安全的。” - http://php.net/manual/en/regexp.reference.escape.php.

除非是 " 或 '.:/

要在 PHP 中转义正则表达式模式变量(或部分变量),请使用 preg_quote()

【讨论】:

【参考方案10】:

要知道什么时候和什么不尝试就可以逃脱,必须准确地理解字符串所经过的上下文链。您将指定从最远端到其最终目的地的字符串,即由正则表达式解析代码处理的内存。

注意内存中的字符串是如何处理的:if 可以是代码中的纯字符串,也可以是输入到命令行的字符串,但 a 可以是交互式命令行,也可以是 shell 脚本中声明的命令行文件,或者代码提到的内存中的变量,或者通过进一步评估的(字符串)参数,或者包含使用任何封装动态生成的代码的字符串......

每个上下文都分配了一些具有特殊功能的字符。

当您想在不使用其特殊功能(上下文本地)的情况下按字面意思传递字符时,您必须为下一个上下文转义它......这可能需要一些其他转义字符,这可能还需要需要在前面的上下文中转义。 此外,可能还有字符编码之类的东西(最阴险的是 utf-8,因为它看起来像普通字符的 ASCII,但甚至可能由终端根据其设置进行可选解释,因此它的行为可能不同,然后是 HTML 的 encoding 属性/XML,有必要准确理解这个过程。

例如命令行中以perl -npe 开头的正则表达式需要转移到一组exec 系统调用,这些系统调用以管道形式连接文件句柄,每个exec 系统调用只有一个参数列表由(非转义)空格分隔,可能还有管道(|)和重定向(> N> N>&M)、括号、*?$(()) 的交互式扩展 ...(所有这些都是特殊的*sh 使用的字符可能会在下一个上下文中干扰正则表达式的字符,但它们的计算顺序是:在命令行之前。命令行被程序读取为 bash/sh/csh/ tcsh/zsh,本质上在双引号或单引号内,转义更简单,但不必在命令行中引用字符串,因为大多数空格必须以反斜杠作为前缀,并且引号不是必需的,因此可以使用扩展功能字符 * 和 ?,但这会解析为与 qu 中不同的上下文奥特。然后,当评估命令行时,在内存中获得的正则表达式(不是在命令行中写入的)接受与在源文件中相同的处理。 对于正则表达式,在方括号 [ ] 中有字符集上下文,perl 正则表达式可以被一大组非 alfa 数字字符引用(例如 m// 或 m:/better/for/path: ...)。

您在其他答案中有更多关于字符的详细信息,这些详细信息非常特定于最终的正则表达式上下文。正如我注意到你提到你发现正则表达式转义与尝试,这可能是因为不同的上下文有不同的字符集,混淆了你对尝试的记忆(通常反斜杠是在那些不同的上下文中用来转义文字字符而不是它的功能的字符)。

【讨论】:

【参考方案11】:

对于 Ionic (Typescript),您必须使用双斜线来转义字符。 例如(这是为了匹配一些特殊字符):

"^(?=.*[\\]\\[!¡\'=ªº\\-\\_ç@#$%^&*(),;\\.?\":|<>\+\\/])"

注意这个] [ - _ . / 字符。它们必须是双斜线。如果你不这样做,你的代码中就会出现类型错误。

【讨论】:

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

正则表达式中必须转义哪些特殊字符?

正则表达式——转义

正则表达式验证密码必须由大小写字母、数字、特殊字符组成

我必须在 Perl 预编译的正则表达式中转义哪些字符?

正则表达式仅匹配未转义的特殊字符

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