Python正则表达式模块是否使用BRE或ERE?

时间:2015-11-25 01:44:29

标签: python regex posix

POSIX似乎将正则表达式实现分为两类:基本正则表达式(BRE)和扩展正则表达式(ERE)。

Python re module引用似乎没有指定。

2 个答案:

答案 0 :(得分:7)

除了语法中的某些相似性外,re模块不遵循正则表达式的POSIX标准

不同的匹配语义

POSIX正则表达式(可以使用DFA / NFA甚至回溯引擎实现)始终找到最左边的最长匹配,而re模块是一个回溯引擎,它找到了最左边的“最早”匹配(根据正则表达式定义的搜索顺序,“最早”)。

(Prefix|PrefixSuffix)PrefixSuffix匹配的情况下,可以观察到匹配语义的差异。

  • 在POSIX-complaint实现POSIX正则表达式(不是只借用语法的那些)中,正则表达式将匹配PrefixSuffix
  • 相比之下,re引擎(以及许多其他回溯正则表达式引擎)仅匹配Prefix,因为在替换中首先指定了Prefix

(xxx|xxxxx)*xxxxxxxxxx(10 x字符串)匹配的情况下也可以看出差异:

  • On Cygwin:

    $ [[ "xxxxxxxxxx" =~ (xxx|xxxxx)* ]] && echo "${BASH_REMATCH[0]}"
    xxxxxxxxxx
    

    所有10个x都匹配。

  • 在Python中:

    >>> re.search(r'(?:xxx|xxxxx)*', 'xxxxxxxxxxx').group(0)
    'xxxxxxxxx'
    

    只有9 x匹配,因为它在所有3次重复中选择交替xxx中的第一项,并且没有任何强制它回溯并在交替中尝试第二项

POSIX独有的正则表达式功能

除了匹配语义的不同之外,POSIX正则表达式还定义了整理符号等价类表达式基于整理的字符范围。这些功能大大提高了正则表达式的表现力。

以等价类表达为例,来自文档:

  

等价类表达式应表示属于等价类的整理元素集,如归类顺序中所述。 [...]。该类应通过将等价类中的任何一个整理元素括在括号相等("[=""=]")分隔符中来表示。 例如,如果'a''à''â'属于同一等价类,则"[[=a=]b]""[[=à=]b]"和{{1}每个都等同于"[[=â=]b]" 。 [...]

由于这些功能在很大程度上取决于区域设置,因此相同的正则表达式在不同的区域设置上的行为可能会有所不同。它还取决于整理顺序的系统上的区域设置数据。

"[aàâb]"正则表达式功能

re借用了Perl的语法,但并非Perl正则表达式中的所有功能都在re中实现。以下是re中可用的一些正则表达式功能,这些功能在POSIX正则表达式中不可用:

  • 贪婪/懒惰量词,指定扩展量词的顺序。

    虽然人们通常在POSIX中调用re贪心,但它实际上只指定了POSIX中重复的下限和上限。所谓的“贪婪”行为是由最左边最长的匹配规则引起的。

  • 环视断言(前瞻和后视)
  • 条件模式*
  • 简写结构:(?(id/name)yes-pattern|no-pattern)\b\s\d(某些POSIX正则表达式引擎可能会实现这些,因为标准会为这些行为保留未定义的行为例)

答案 1 :(得分:5)

都不是。它基本上是PCRE方言,但却是一种独特的实现方式。

re文档中的第一句话说:

  

此模块提供类似于Perl中的正则表达式匹配操作。

虽然这并没有立即向新手透露它们与例如POSIX正则表达式应该是常识,Perl 4及更高版本的Perl 5提供了早期工具的正则表达式功能的大幅扩展功能集,包括POSIX对grep -E又称ERE的强制要求。

perlre manual page更详细地描述了正则表达式功能,尽管您可以在Python文档中以不同的形式找到相同的详细信息。 Perl手册页包含以下历史记录:

  

Perl模式匹配中使用的模式是从版本8正则表达式例程中提供的模式演变而来的。 (这些例程是由Henry Spencer自由重新发布的V8例程重新实现而得到的(远程)。)

(此处,V8指的是Version 8 Unix。斯宾塞的图书馆基本上是(re)implemented POSIX regular expressions。)

Perl 4有大量便利结构,如\d\s\w以及\t\f,{{等符号短语1}}。 Perl 5添加了一组重要的扩展(仍在缓慢增长),包括但不限于

  • 非贪婪量词
  • 非回溯量词
  • Unicode符号和属性支持
  • 非分组括号
  • Lookaheads和lookbehinds
  • ...基本上以\n
  • 开头的任何内容

结果,"常规"表达绝不是严格的"常规"不再。

这是由Philip Hazell在便携式库中重新实现的,最初是用于Exim邮件服务器;他的PCRE library已经进入无数不同的应用程序,包括许多编程语言(Ruby,PHP,Python等)。顺便提一下,尽管有这个名字,但图书馆并不是严格的和Perl兼容的#34; (不再);在功能和行为方面存在差异。 (例如,Perl在内部将(?更改为*,而PCRE会执行其他操作。)

早期版本的Python实际上有一个不同的正则表达式实现,并且有plans to change it again(尽管它基本上仍然是PCRE)。这是Python 2.7 / 3.5的情况。