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


389

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

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


4
好的正则表达式库具有类似“ escape()”的功能,以允许使用任意字符串作为正则表达式部分。
ivan_pozdeev

2
您可以使用gskinner.com/RegExr等在线Regex表达式检查器(免费)。(输入,然后将鼠标悬停在您输入的正则表达式上)
hexicle

2
转义所有非字母数字字符。期。
Salman von Abbas

2
此问题已添加到“其他”下的“ 堆栈溢出正则表达式常见问题解答 ”中。
aliteralmind 2014年

1
此问题已添加到“转义序列”下的堆栈溢出正则表达式常见问题解答中
aliteralmind 2014年

Answers:


365

实际上,您必须转义哪些字符以及您必须避免转义哪些字符确实取决于您使用的正则表达式风格。

对于PCRE和大多数其他所谓的Perl兼容口味,请避免使用以下外部字符类:

.^$*+?()[{\|

以及这些内部字符类:

^-]\

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

.^$*+?()[{\|

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

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

[]^-]

在POSIX基本正则表达式(BRE)中,这些是元字符,您需要对其进行转义以隐藏其含义:

.^$*[\

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

在角色类中,BRE与ERE遵循相同的规则。

如果所有这些使您的头部旋转,请抓住RegexBuddy的副本。在“创建”选项卡上,单击“插入令牌”,然后单击“文字”。RegexBuddy将根据需要添加转义符。


1
在我看来,您忘记了“ /”,也需要在类外转义。
jackthehipster

11
/在我提到的任何正则表达式形式中,它都不是元字符,因此正则表达式语法不需要将其转义。当一个正则表达式引述的编程语言文字,那么,语言的字符串或正则表达式格式规则可能要求/"'进行转义,甚至可能需要`\`要倍加逃脱。
Jan Goyvaerts 2015年

2
那冒号“:”呢?是否可以在字符类内部以及外部进行转义?en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions说:“ PCRE具有一致的转义规则:任何非字母数字字符都可以转义以表示其字面值。”
nicolallias 2015年

4
可以逃脱与应该逃脱不同。PCRE语法从不需要转义文字冒号,因此转义文字冒号只会使您的正则表达式更难以阅读。
Jan Goyvaerts 2015年

1
对于非POSIX ERE(我最常用的一种,因为它是Tcl所实现的)转义其他内容不会产生错误。
slebetman

61

现代RegEx香精(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兼容性可能会有所不同

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


旧版RegEx口味(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来测试你的表情生活

1
您的答案有很多错误,包括但不限于:您的任何“现代”风格都不需要-]可以在字符类之外进行转义。POSIX(BRE / ERE)在字符类中没有转义字符。Delphi的RTL中的正则表达式实际上是基于PCRE的。Python,Ruby和XML具有自己的风格,与POSIX风格更接近PCRE。
Jan Goyvaerts

1
@JanGoyvaerts感谢您的纠正。您提到的味道确实更接近PCRE。至于逃生,为了简单起见,我一直将它们保留下来。比起一些例外情况,记住逃避各地更容易记住。如果高级用户想要避免一些反斜杠,他们将知道发生了什么。无论如何,我用一些澄清更新了我的答案,希望可以解决其中的一些问题。
Beejor

22

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

但是,保留正则表达式工具页面或此正则表达式备忘单之类的页面可以大大帮助您快速过滤掉内容。


1
Addedbytes备忘单被大大简化了,并且存在一些明显的错误。例如,它说\<\>是单词边界,在Boost regex库中仅适用(AFAIK)。但在其他地方它说<>是元字符,必须进行转义(以\<\>)逐字匹配他们,这不是真正的在任何味道
艾伦·摩尔

5

不幸的是,诸如(和\(之类的东西)的含义在Emacs样式正则表达式和大多数其他样式之间交换。因此,如果尝试转义这些样式,则可能与您想要的相反。

因此,您确实必须知道您要引用哪种样式。


5

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

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

查阅Jeff Friedl的《精通正则表达式》一书。


4

真的没有。大约有一半的正则表达式语法;他们似乎可以归结为Perl,EMACS / GNU和AT&T,但我也总是感到惊讶。


4

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

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

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

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

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

BTW字符类是漂亮的正则表达式组成部分,因此它们在大多数需要在正则表达式中转义字符的情况下都可以使用。

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

您可能想看一本“闪亮的书”,又称“有效Perl”(经过消毒的Amazon链接),特别是有关正则表达式的章节,以了解正则表达式引擎评估类型的不同之处。

并非全世界都是PCRE!

无论如何,与SNOBOL相比,regexp是如此笨拙!现在,这是一个有趣的编程课程!与Simula上的那个一起

七十年代末在UNSW学习的乐趣啊!(-:


'sed'是一个命令,其普通的'('不是特别的,但是'\('是特别的;相反,PCRE颠倒了含义,所以'('是特别的,但是'\('不是。这正是OP正在询问
Jonathan Leffler'

sed是一个* nix实用程序,它使用最原始的regexp评估集之一。PCRE不会进入我所描述的情况,因为它涉及到另一类(自动)有限自动机,并且它评估正则表达式的方式。我认为我对最小化正则表达式语法的建议仍然成立。
罗伯·威尔斯,

1
在符合POSIX的系统上,sed使用POSIX BRE,我将在其答案中进行介绍。现代Linux系统上的GNU版本使用带有一些扩展的POSIX BRE。
Jan Goyvaerts


2

要准确地理解字符串所经过的上下文链,必须知道何时以及什么情况下无需进行尝试就可以逃脱。您将指定从最远端到最终目标的字符串,该目标是由regexp解析代码处理的内存。

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

每个上下文都为某些字符分配了特殊功能。

当您想直接使用字符而不使用其特殊功能(对于上下文而言是本地的)时,对于这种情况,您必须对其进行转义,对于下一个上下文...这可能需要一些其他转义字符,可能还需要在前面的上下文中转义了。此外,可能还有字符编码之类的东西(最阴险的是utf-8,因为它看起来像ASCII的普通字符,但是即使终端根据其设置也可能会对其进行可选解释,因此其行为可能不同,然后是HTML的编码属性/ XML,有必要正确地了解该过程。

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

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



0

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

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

注意这个] [ - _ . /字符。他们必须被大大削减。如果不这样做,您的代码中将出现类型错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.