POSIX似乎将正则表达式实现分为两种:基本正则表达式(BRE)和扩展正则表达式(ERE)。Python re module参考似乎没有指定。
re
7gs2gvoe1#
除了语法上的一些相似之处,re模块不遵循正则表达式的POSIX标准。
POSIX正则表达式(可以用DFA/NFA甚至回溯引擎实现)总是找到最左边的最长匹配,而re模块是一个回溯引擎,它找到最左边的“最早”匹配(根据正则表达式定义的搜索顺序,“最早”)。在匹配(Prefix|PrefixSuffix)与PrefixSuffix的情况下,可以观察到匹配语义的差异。
(Prefix|PrefixSuffix)
PrefixSuffix
Prefix
在匹配(xxx|xxxxx)*和xxxxxxxxxx(10个x的字符串)的情况下,也可以看到这种差异:
(xxx|xxxxx)*
xxxxxxxxxx
x
$ [[ "xxxxxxxxxx" =~ (xxx|xxxxx)* ]] && echo "${BASH_REMATCH[0]}" xxxxxxxxxx
所有10个x都匹配。
>>> re.search(r'(?:xxx|xxxxx)*', 'xxxxxxxxxxx').group(0) 'xxxxxxxxx'
只有9个x匹配,因为它在所有3次重复中选择了交替中的第一个项目xxx,并且没有任何东西迫使它回溯并尝试交替中的第二个项目。
xxx
POSIX正则表达式除了在匹配语义上的差异外,还定义了排序符号、等价类表达式、基于排序的字符范围的语法,这些特性极大地增强了正则表达式的表达能力。以等价类表达式为例,来自文档:等价类表达式应表示属于等价类的排序元素的集合,如排序顺序中所述。[...]。该类应通过将等价类中的任何一个排序元素包含在括号-equal中来表示("[="和"=]")分隔符。例如,如果'a'、'à'和'â'属于同一等价类,则"[[=a=]b]"、"[[=à=]b]"、和"[[=â=]b]"各自等价于"[aàâb]"。[...]由于这些特性很大程度上依赖于语言环境设置,因此同一个正则表达式在不同的语言环境下可能会有不同的行为。它还依赖于系统上的语言环境数据来确定排序规则。
"[="
"=]"
'a'
'à'
'â'
"[[=a=]b]"
"[[=à=]b]"
"[[=â=]b]"
"[aàâb]"
re借用了Perl的语法,但并不是Perl正则表达式中的所有功能都在re中实现。下面是一些在re中可用的正则表达式功能,这些功能在POSIX正则表达式中不可用:
虽然人们通常把POSIX中的*称为贪婪,但它实际上只指定了POSIX中重复的下限和上限,所谓的“贪婪”行为是由于最左边的最长匹配规则。
*
(?(id/name)yes-pattern|no-pattern)
\b
\s
\d
\w
oaxa6hgo2#
两者都不是。它基本上是PCRE方言,但它是一个不同的实现。re文档中的第一句话是:该模块提供了与Perl中的操作类似的正则表达式匹配操作。虽然这并不能立即向新手揭示它们与POSIX正则表达式的关系,但应该知道Perl 4和后来的Perl 5提供了比早期工具的正则表达式功能更丰富的功能集,包括POSIX对grep -E(又名ERE)的强制要求。perlre manual page更详细地描述了正则表达式的特性,尽管你会在Python文档中以不同的形式找到相同的细节。Perl手册页包含了这段历史:Perl模式匹配中使用的模式是从Version 8 regex例程中提供的那些模式发展而来的(这些例程是从亨利Spencer对V8例程的可自由再分发的重新实现中派生出来的)。(Here Spencer的库基本上(重新)实现了POSIX正则表达式。)Perl 4有大量的方便结构,如\d,\s,\w以及符号简写,如\t,\f,\n。Perl 5添加了一组重要的扩展(仍在缓慢增长),包括但不限于:
grep -E
perlre
\t
\f
\n
(?
因此,“正则”表达式不再是严格的“正则”表达式。这是由Philip Hazel在一个可移植库中重新实现的,最初是为Exim邮件服务器;他的PCRE library已经在无数不同的应用程序中找到了自己的方式,包括许多编程语言(Ruby、PHP、Python等)。在特性和行为上都有区别。(例如,Perl在内部将*更改为类似{0,32767}的东西,而PCRE则执行其他操作。)Python的早期版本实际上有一个不同的正则表达式实现,有plans to change it again(尽管它基本上仍然是PCRE)。这是Python 2.7 / 3.5的情况。
{0,32767}
2条答案
按热度按时间7gs2gvoe1#
除了语法上的一些相似之处,
re
模块不遵循正则表达式的POSIX标准。匹配语义不同
POSIX正则表达式(可以用DFA/NFA甚至回溯引擎实现)总是找到最左边的最长匹配,而
re
模块是一个回溯引擎,它找到最左边的“最早”匹配(根据正则表达式定义的搜索顺序,“最早”)。在匹配
(Prefix|PrefixSuffix)
与PrefixSuffix
的情况下,可以观察到匹配语义的差异。PrefixSuffix
。re
引擎(以及许多其他回溯正则表达式引擎)将只匹配Prefix
,因为Prefix
在交替中首先指定。在匹配
(xxx|xxxxx)*
和xxxxxxxxxx
(10个x
的字符串)的情况下,也可以看到这种差异:所有10个
x
都匹配。只有9个
x
匹配,因为它在所有3次重复中选择了交替中的第一个项目xxx
,并且没有任何东西迫使它回溯并尝试交替中的第二个项目。POSIX独占的正则表达式特性
POSIX正则表达式除了在匹配语义上的差异外,还定义了排序符号、等价类表达式、基于排序的字符范围的语法,这些特性极大地增强了正则表达式的表达能力。
以等价类表达式为例,来自文档:
等价类表达式应表示属于等价类的排序元素的集合,如排序顺序中所述。[...]。该类应通过将等价类中的任何一个排序元素包含在括号-equal中来表示(
"[="
和"=]"
)分隔符。例如,如果'a'
、'à'
和'â'
属于同一等价类,则"[[=a=]b]"
、"[[=à=]b]"
、和"[[=â=]b]"
各自等价于"[aàâb]"
。[...]由于这些特性很大程度上依赖于语言环境设置,因此同一个正则表达式在不同的语言环境下可能会有不同的行为。它还依赖于系统上的语言环境数据来确定排序规则。
re
正则表达式特性re
借用了Perl的语法,但并不是Perl正则表达式中的所有功能都在re
中实现。下面是一些在re
中可用的正则表达式功能,这些功能在POSIX正则表达式中不可用:虽然人们通常把POSIX中的
*
称为贪婪,但它实际上只指定了POSIX中重复的下限和上限,所谓的“贪婪”行为是由于最左边的最长匹配规则。(?(id/name)yes-pattern|no-pattern)
\b
、\s
、\d
、\w
(一些POSIX正则表达式引擎可能实现这些,因为标准未定义这些情况的行为)oaxa6hgo2#
两者都不是。它基本上是PCRE方言,但它是一个不同的实现。
re
文档中的第一句话是:该模块提供了与Perl中的操作类似的正则表达式匹配操作。
虽然这并不能立即向新手揭示它们与POSIX正则表达式的关系,但应该知道Perl 4和后来的Perl 5提供了比早期工具的正则表达式功能更丰富的功能集,包括POSIX对
grep -E
(又名ERE)的强制要求。perlre
manual page更详细地描述了正则表达式的特性,尽管你会在Python文档中以不同的形式找到相同的细节。Perl手册页包含了这段历史:Perl模式匹配中使用的模式是从Version 8 regex例程中提供的那些模式发展而来的(这些例程是从亨利Spencer对V8例程的可自由再分发的重新实现中派生出来的)。
(Here Spencer的库基本上(重新)实现了POSIX正则表达式。)
Perl 4有大量的方便结构,如
\d
,\s
,\w
以及符号简写,如\t
,\f
,\n
。Perl 5添加了一组重要的扩展(仍在缓慢增长),包括但不限于:(?
开头的内容因此,“正则”表达式不再是严格的“正则”表达式。
这是由Philip Hazel在一个可移植库中重新实现的,最初是为Exim邮件服务器;他的PCRE library已经在无数不同的应用程序中找到了自己的方式,包括许多编程语言(Ruby、PHP、Python等)。在特性和行为上都有区别。(例如,Perl在内部将
*
更改为类似{0,32767}
的东西,而PCRE则执行其他操作。)Python的早期版本实际上有一个不同的正则表达式实现,有plans to change it again(尽管它基本上仍然是PCRE)。这是Python 2.7 / 3.5的情况。