我已经厌倦了在使用许多正则表达式实现时,总是试图猜测是否应该转义特殊字符如'()[]{}|
'等。
例如Python、sed、grep、awk、Perl、rename、Apache、find等都不同。是否有规则集可以告诉我何时应该转义特殊字符,何时不应该转义? 是否取决于正则表达式类型,如PCRE、POSIX或扩展正则表达式?
我已经厌倦了在使用许多正则表达式实现时,总是试图猜测是否应该转义特殊字符如'()[]{}|
'等。
例如Python、sed、grep、awk、Perl、rename、Apache、find等都不同。是否有规则集可以告诉我何时应该转义特殊字符,何时不应该转义? 是否取决于正则表达式类型,如PCRE、POSIX或扩展正则表达式?
你需要转义哪些字符,以及哪些字符不需要转义,实际上取决于你使用的正则表达式引擎。
对于 PCRE 和大多数称为 Perl 兼容的引擎,在字符类之外需要转义以下字符:
.^$*+?()[{\|
还有这些字符类里面的内容:
^-]\
对于POSIX扩展正则表达式(ERE),在字符类之外需要转义这些字符 (与PCRE相同):
.^$*+?()[{\|
在 POSIX ERE 中,转义任何其他字符都是错误的。
在字符类内部,反斜杠是 POSIX 正则表达式中的字面字符。您不能使用它来转义任何内容。如果要将字符类元字符包含为文字字符,则必须使用“巧妙的放置”。 将 ^ 放在任何位置除了开头,将 ] 放在开头,将 - 放在字符类的开头或结尾以匹配这些文字,例如:
[]^-]
在 POSIX 基本正则表达式(BRE)中,这些是元字符,需要转义才能取消它们的含义:.^$*[\
在BRE中转义括号和花括号会使它们具有ERE中未转义版本的特殊含义。某些实现(例如GNU)在转义时还会赋予其他字符特殊含义,例如\?和+。除了. ^ $ * () {}之外转义其他字符通常是BRE中的错误。
在字符类中,BRE遵循与ERE相同的规则。
如果所有这些让您感到头晕,请获取RegexBuddy副本。在“创建”选项卡上,单击“插入令牌”,然后选择“字面量”。RegexBuddy将根据需要添加转义。
/
不是元字符,因此正则表达式语法不需要对其进行转义。当在编程语言中引用正则表达式时,该语言的字符串或正则表达式格式规则可能需要对/
、"
或'
进行转义,甚至可能需要双重转义\\
。 - Jan Goyvaertsconst escapePCRE = string => string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
,来源于 Mozilla 开发者网络。 - Константин Ван包括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兼容性可能会有所不同。
任何地方都可以使用: . ^ $ * + - ? ( ) [ ] { } \ |
包括awk、ed、egrep、emacs、GNUlib、grep、PHP(ereg)、MySQL、Oracle、R、sed。
在后续版本或使用扩展程序中可以启用PCRE支持。
ERE/awk/egrep/emacs
字符类外部: . ^ $ * + ? ( ) [ { } \ |
字符类内部: ^ - [ ]
BRE/ed/grep/sed
字符类外部: . ^ $ * [ \
字符类内部: ^ - [ ]
对于字面量,不需要转义:+ ? ( ) { } |
对于标准正则表达式行为,需要转义:\+ \? \( \) \{ \} \|
\xFF
进行转义] -
需要进行转义,但我将它们放在单个列表中以保持简洁。"(\")(/)(\\.)"
与/(")(\/)(\.)/
之间的区别)。-
或]
。POSIX(BRE/ERE)在字符类内部没有转义字符。Delphi RTL中的正则表达式风格实际上是基于PCRE的。Python、Ruby和XML都有自己的正则表达式风格,更接近于PCRE而不是POSIX风格。 - Jan GoyvaertsPOSIX识别基本正则表达式(BRE)和扩展正则表达式(ERE)的多种变体。即使如此,由于POSIX标准化的实用程序的历史实现,仍存在一些怪癖。
没有一个简单的规则来确定何时使用哪种符号表示法,甚至无法确定给定命令使用哪种符号表示法。
请查看Jeff Friedl的Mastering Regular Expressions书籍。
很不幸,像(和\(这样的符号在Emacs风格的正则表达式和大多数其他风格之间的含义是相反的。因此,如果你试图转义它们,你可能会做与你想要的相反的事情。
所以你真的需要知道你要引用哪种风格。
https://perldoc.perl.org/perlre.html#Quoting-metacharacters和https://perldoc.perl.org/functions/quotemeta.html
my $regex = quotemeta($string);
s/$regex/something/
实际上,没有一个固定的正则表达式语法。目前已有约数千种不同的正则表达式语法,主要分为Perl、EMACS/GNU和AT&T等几种类型,但我也经常会感到惊讶。
sed -e 's/foo\(bar/something_else/'
sed -e 's/foo[(]bar/something_else/'
我发现这个方法适用于大多数正则表达式实现。
顺便说一下,字符类是相当普通的正则表达式组件,因此它们往往在需要在正则表达式中转义字符的大多数情况下都能工作。
编辑:在下面的评论之后,我想提一下,在查看正则表达式评估行为时,您还必须考虑有限状态自动机和非有限状态自动机之间的区别。
您可能会想看看“闪亮的球书”(Effective Perl)(经过消毒的亚马逊链接),特别是关于正则表达式的章节,以了解正则表达式引擎评估类型的差异。
并非所有的世界都是PCRE!
无论如何,与SNOBOL相比,正则表达式都很笨重!那真是一门有趣的编程课程!连同Simula一起学习。
啊,70年代末在UNSW学习的乐趣!(-:
perl -npe
开头的正则表达式需要转换为一组exec系统调用,这些系统调用将文件句柄作为管道连接,每个这些系统调用只有由(未转义)空格分隔的参数列表,并且可能是管道(|)和重定向(> N> N>&M),括号,*
和?
的交互扩展,$(())
...(所有这些都是*sh使用的特殊字符,可能会干扰下一个上下文中的正则表达式字符,但它们按顺序评估:在命令行之前。命令行由bash / sh / csh / tcsh / zsh等程序读取,本质上在双引号或单引号内,转义更简单,但不必在命令行中引用字符串,因为大多数情况下必须在空格前加上反斜杠,而引号不是必需的,使字符*和?的扩展功能可用,但是在引号中解析为不同的上下文。然后,当评估命令行时,内存中获得的正则表达式(不是按照命令行编写的)接收与在源文件中一样的处理。
escape()
”这样的函数,允许使用任意字符串作为正则表达式的一部分。 - ivan_pozdeev