- 一、正则表达式引擎
- 二、正则表达式分类
- 三、正则表达式比较
- 四、Linux/OS X 下常用命令与正则表达式的关系
正则引擎大体上可分为不同的两类:DFA
和 NFA
,而 NFA
又基本上可以分为传统型 NFA
和 POSIX NFA
。
-
DFA(Deterministic Finite Automaton)
确定型有穷自动机 -
NFA(Non-deterministic finite automaton)
非确定型有穷自动机 (1) Traditional NFA (2) POSIX NFA
DFA
引擎因为不需要回溯,所以匹配快速,但不支持捕获组,所以也就不支持反向引用和 $number
这种引用方式,目前使用 DFA
引擎的语言和工具主要有 awk
、egrep
和 lex
。
POSIX NFA
主要指符合 POSIX
标准的 NFA
引擎,它的特点主要是提供 longest-leftmost
匹配,也就是在找到最左侧最长匹配之前,它将继续回溯。同 DFA
一样,非贪婪模式或者说忽略优先量词对于 POSIX NFA
同样是没有意义的。
目前 JavaScript,Java,Php,Python,C# 等语言均实现了 NFA 引擎。
大多数语言和工具使用的是传统型的 NFA
引擎,它有一些 DFA
不支持的特性:
-
捕获组、反向引用和
$number
引用方式; -
环视(Lookaround),
(?(?=…)
、(?!…)
,或者有的有文章叫做预搜索; -
忽略优先量词
??
、*?
、+?
、{m,n}?
、{m,}?
,或者有的文章叫做非贪婪模式; -
占有优先量词
?+
、*+
、++
、{m,n}+
、{m,}+
,目前仅Java
和PCRE
支持,固化分组(?>…)
。
按以上的说法,awk、egrep、lex 使用 DFA 引擎,所以不支持捕获组、反向引用和 $number 引用方式;不支持环视;不支持忽略优先修饰符;不支持占有优先修饰符。我觉得有问题,改天再验证吧!!
二、正则表达式分类在 Linux 和 OS X 下,常见的正则表达式,至少有以下三种:
- 基本的正则表达式(Basic Regular Expression 又叫 Basic RegEx 简称 BREs)
- 扩展的正则表达式(Extended Regular Expression 又叫 Extended RegEx 简称 EREs)
- Perl 的正则表达式(Perl Regular Expression 又叫 Perl RegEx 简称 PREs)
^
匹配行首或者字符串的开始处^
^
^
^
$
匹配行尾或者字符串的结尾处$
$
$
$
^$
匹配空行^$
^$
^$
^$
\
匹配单词结尾处,这种元字符的含义有问题>
>
不支持不支持,但是可以使用 \b
来匹配单词边界?
匹配前面的子表达式 0 次或者 1 次;匹配前面的子表达式 0 个或 1 个;匹配 0 个或 1 个前面的子表达式;匹配 0 个或 1个前面的子表达式所代指的字符串;匹配 0 个或 1 个前面的子表达式所匹配到的字符串不支持,需要转义?
?
?
\?
匹配前面的子表达式 0 次或者 1 次,这种元字符的含义有问题\?
不支持不支持不支持?
问号跟在任何一个量词后面,则变成非贪婪匹配模式。不支持不支持不支持不支持.
匹配除了换行符以外的任意一个字符(awk 指令中的句点 .
可以匹配换行符 \n
).
.
(如果要匹配包含换行符在内的任意单个字符,可以使用 [\s\S]
).
.
(如果要匹配包含 \n
在内的任意一个字符,可以使用 [.\n]
)*
匹配前面的子表达式任意次;匹配前面的子表达式任意个;匹配任意次前面的子表达式*
*
*
*
+
匹配前面的子表达式 1 次或者多次需要转义+
+
+
{n}
n
是一个非负整数,表示匹配前面的子表达式 n
次需要转义,\{n\}
{n}
{n}
{n}
x|y
匹配 x 或者 y需要转义,x\|y
x|y
x|y
x|y
\d
匹配从 0 到 9 中的任意一个数字字符不支持不支持\d
\d
\D
匹配非数字的任意一个字符不支持不支持\D
\D
\S
匹配除了空白字符以外的任意一个字符不支持不支持\S
\S
\s
匹配任意一个空白字符,等价于 [\f\n\r\t\v]
不支持不支持\s
\s
\W
匹配除了英文字母、数字、下划线以外的任意一个字符\W
\W
\W
\W
\w
匹配英文字母、数字、下划线中的任意一个字符\w
\w
\w
\w
\B
匹配非单词边界,例如,er\B
可以匹配 here
中的 er
,但是不能匹配 hier
中的 er
\B
\B
\B
\B
\b
匹配单词边界\b
\b
\b
\b
\f
匹配一个换页符。等价于 \x0c
和 \cL
不支持不支持\f
\f
\n
匹配一个换行符。等价于 \x0a
和 \cJ
不支持不支持\n
\n
\r
匹配一个回车符。等价于 \x0d
和 \cM
不支持不支持\r
\r
\t
匹配一个横向制表符。等价于 \x09
和 \cI
不支持不支持\t
\t
\v
匹配一个垂直制表符。等价于 \x0b
和 \cK
不支持不支持\v
\v
\cx
匹配由 x
指明的控制字符。例如,\cM
匹配一个 Control-M
或回车符,x
的值必须为一个英文字母,否则 c 被视为一个普通字符不支持不支持\cx
\xn
匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,\x41
匹配 A
。正则表达式中可以使用 ASCII 编码。不支持不支持支持\num
其中 num 为一个正整数,表示对所获取的匹配的引用不支持\num
\num
注意:
- js 中支持的是 EREs。
- 当使用 BREs ( 基本正则表达式 ) 时,必须在下列这些符号
?,+,|,{,},(,)
前加上转义字符。
我曾经尝试在 grep 和 sed 命令中书写正则表达式,经常发现某些元字符不能直接使用,有些需要转义,有些又不需要转义,下面就梳理了不同的命令所支持的正则表达式种类。
命令正则表达式特定grep