Answers:
不幸的是,由于历史原因,不同的工具使用的正则表达式语法略有不同,有时某些实现具有其他工具不支持的扩展。尽管有一个共同点,但似乎每个工具编写者都做出了不同的选择。
结果是,如果您有一个可以在一个工具中使用的正则表达式,则可能需要对其进行修改才能在另一个工具中使用。常用工具之间的主要区别是:
+?|(){}
需要反斜杠;.[]*^$
,通常还支持哪些扩展+?|()
在此答案中,我列出了主要标准。有关详细信息,请查看所用工具的文档。
Wikipedia 对正则表达式引擎的比较有一张表格,列出了常见实现所支持的功能。
基本的正则表达式由POSIX标准编写。它是由使用的语法grep
,sed
和vi
。此语法提供以下功能:
^
并且$
仅在行的开头和结尾匹配。.
匹配任何字符(或换行符以外的任何字符)。[…]
与括号(字符集)内列出的任何一个字符匹配。如果左括号后面的第一个字符是a ^
,则匹配未列出的字符。要包含]
,请将其放在开头之后[
(或[^
如果是负数之后)。如果-
在两个字符之间,则表示一个范围;包含文字-
,将其放在无法解析为范围的位置。^$.*\[
引号前的反斜杠都将下一个字符引起来。*
与前面的字符或子表达式匹配0、1或多次。\(…\)
是一个语法组,用于*
运算符或反向引用和\DIGIT
替换。\1
,,\2
…匹配与相应组匹配的精确文本,例如,但不\(fo*\)\(ba*\)\1
匹配。没有标准的方式来指代第十组及以后的组(标准含义是第一组,后跟a )。foobaafoo
foobaafo
\10
0
以下功能也是标准功能,但某些受限制的实现中缺少这些功能:
\{m,n\}
在m到n次之间匹配前面的字符或子表达式;n或m可以省略,并且恰好表示m。\{m\}
[[:alpha:]]
匹配任何字母。现代的实现方括号表达式)还包括排序元素像[.ll.]
和等价类等[=a=]
。以下是常见的扩展(尤其是在GNU工具中),但并非在所有实现中都可以找到。查看所用工具的手册。
\|
交替显示:foo\|bar
匹配foo
或bar
。\?
(简称\{0,1\}
)和\+
(简称\{1,\}
)分别与前面的字符或子表达式最多匹配1次,或至少匹配1次。\n
与换行符,\t
制表符等匹配。\w
匹配任何单词组成部分([_[:alnum:]]
是本地化的缩写,但有变化),并且\W
匹配任何非单词组成部分的字符。\<
并且\>
仅在单词的开头或结尾分别匹配空字符串;\b
要么\B
匹配,要么\b
不匹配。请注意,没有\|
运算符的工具没有正则表达式的全部功能。向后引用允许在数学意义上用正则表达式无法完成的一些额外操作。
扩展的正则表达式由POSIX标准编码。与BRE相比,它们的主要优点是规则性:所有标准运算符都是裸露的标点符号,在标点符号之前总是加反斜杠。它是awk
,grep -E
或egrep
,GNU sed -r
和bash的=~
运算符使用的语法。此语法提供以下功能:
^
并且$
仅在行的开头和结尾匹配。.
匹配任何字符(或换行符以外的任何字符)。[…]
与括号(字符集)内列出的任何一个字符匹配。带有首字母^
和范围的补码的工作方式类似于BRE(请参见上文)。可以使用字符类,但是一些实现中没有。现代实现还支持等效类和整理元素。括号内的反斜杠在某些(但不是全部)实现中引用了下一个字符;用于\\
表示可移植性的反斜杠。(…)
是一个语法组,用于*
或\DIGIT
替代。|
交替显示:foo|bar
匹配foo
或bar
。*
,+
并且?
与前面的字符或子表达式多次匹配:表示0或更多*
,表示1或更多+
,表示0或1 ?
。{m,n}
在m和n次之间匹配前面的字符或子表达式(某些实现中缺少);n或m可以省略,并且恰好表示m。{m}
\DIGIT
$0 ~ "(...)\\1"
\n
\t
\b
\B
\b
\B
PCRE是ERE的扩展,它最初是由Perl引入并由GNU grep -P
和许多现代工具和编程语言采用的,通常是通过PCRE库。请参阅Perl文档以获取带有示例的良好格式。PCRE并不支持最新版本的Perl的所有功能(例如,仅Perl支持Perl代码执行)。有关支持的功能的摘要,请参见PCRE手册。ERE的主要新增功能包括:
(?:…)
是一个非捕获组:like (…)
,但不计入反向引用。(?=FOO)BAR
(超前)匹配项BAR
,但前提是FOO
在相同位置也有匹配项。锚定匹配项而不在匹配项中包含以下文本是最有用的:foo(?=bar)
匹配项,foo
但仅在其后跟bar
。(?!FOO)BAR
(负向超前)匹配BAR
,但FOO
在同一位置也没有匹配。例如,(?!foo)[a-z]+
匹配不以foo
;开头的任何小写单词;[a-z]+(?![0-9)
匹配任何不带数字的小写单词(因此,在中foo123
,它匹配fo
但不匹配foo
)。(?<=FOO)BAR
(lookbehind)匹配项BAR
,但前提是它紧跟在之前FOO
。FOO
必须具有已知长度(您不能使用诸如的重复运算符*
)。这对于锚定匹配项而不在匹配项中包含前面的文本是最有用的:(?<=^| )foo
匹配项,foo
但前提是它前面有空格或字符串的开头。(?<!FOO)BAR
(负向后搜索)匹配项BAR
,但前提是该匹配项没有紧随其后FOO
。FOO
必须具有已知长度(您不能使用诸如的重复运算符*
)。这对于锚定匹配项而不在匹配项中包含前面的文本非常有用:(?<![a-z])foo
匹配项,foo
但前提是该匹配项前面没有小写字母。Emacs的语法介于BRE和ERE之间。除了Emacs之外,它也是-regex
GNU find中的默认语法。Emacs提供以下运算符:
^
,$
,.
,[…]
,*
,+
,?
在ERE\(…\)
,\|
,\{…\}
,在BRE\DIGIT
\<
和\>
word边界; 以及Emacs的最新版本中的更多内容,其他类似Emacs语法的引擎通常不支持。Shell Glob(通配符)使用与正则表达式完全不同且功能较弱的语法执行模式匹配。除外壳程序外,这些通配符还可与find -name
和rsync过滤器等其他工具一起使用。POSIX模式包括以下功能:
?
匹配任何单个字符。[…]
是常用正则表达式语法中的字符集。一些外壳程序不支持字符类。有些shell需要!
而不是^
否定集合。*
匹配任何字符序列(通常/
在匹配文件路径时除外;如果/
从中排除*
,则**
有时包括/
,但请查看工具的文档)。Ksh提供了其他功能,使其模式与正则表达式的全部功能相匹配。运行后,这些功能也可以在bash中使用shopt -s extglob
。Zsh具有不同的语法,但在之后也可以支持ksh的语法setopt ksh_glob
。
grep
...)。除了之外,该工具集很少在AT&T之外找到。tw
expr
ksh
regex(7)
您同意并称其为[these]
“括号表达式”和(在“括号表达式”之内)为[:these:]
“字符类”。我不确定如何最好地解决这个问题。
-
指定了一个范围,并且应该^
从字面上进行转义,首先(在optional之后),或者最后一次转义。(我已经看到了很多错误,例如,– [A-z]
注意大小写的变化–匹配代码65至122的字符,并且不小心包括以下每个字符:[\]^_`
。我也看到了有效但混淆[!-~]
了ANSI中所有可打印字符的错误,我更喜欢将其视为[\x21-\x7e]
,尽管在不同的方面令人困惑,但它的动作至少很直接。)
vim
的和AT&T的libast(如ksh93
)。