Python中的Perl兼容正则表达式(PCRE)

2024-05-12 23:56:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我不得不在Python中解析一些基于PCRE的字符串,我不知道该怎么做。

我要分析的字符串如下:

match mysql m/^.\0\0\0\n(4\.[-.\w]+)\0...\0/s p/MySQL/ i/$1/

在本例中,我必须获得以下不同的项:

"m/^.\0\0\0\n(4\.[-.\w]+)\0...\0/s" ; "p/MySQL/" ; "i/$1/"

我在Python中发现的唯一与PCRE操作相关的是这个模块:http://pydoc.org/2.2.3/pcre.html(但它是一个.so文件…)

您知道是否存在用于解析此类字符串的Python模块吗?


Tags: 模块文件字符串orghttpsohtmlmatch
3条回答

因为您想运行PCRE regex,而Python的re模块已经偏离了它最初的PCRE源代码,所以您可能还想签出Arkadiusz Wahlig's Python bindings for PCRE。这样您就可以访问本地PCRE,不需要在regex风格之间进行转换。

你在找'(\w/[^/]+/\w*)'

像这样使用

import re
x = re.compile('(\w/[^/]+/\w*)')
s = 'match mysql m/^.\0\0\0\n(4\.[-.\w]+)\0...\0/s p/MySQL/ i/$1/'
y = x.findall(s)
# y = ['m/^.\x00\x00\x00\n(4\\.[-.\\w]+)\x00...\x00/s', 'p/MySQL/', 'i/$1/']

是在玩Edi Weitz的Regex Coach时发现的,所以感谢对这个问题的评论,让我记住了它的存在。

特别注意Python中的非ASCII

Python在模式和字符串中如何处理或未能处理非ASCII存在一些非常微妙的问题。更糟糕的是,这些差异很大程度上取决于您使用的Python版本,还取决于您是否有一个“广泛的构建”。

一般来说,在进行Unicode工作时,具有宽构建的Python 3工作得最好,而具有窄构建的Python 2工作得最差,但是所有的组合与Perl regex相对于Unicode的工作方式仍然相去甚远。如果您要在Python中寻找模式,那么您可能需要比它原来的re模块看得更远一些。

如果您使用足够高级的Python版本,那么恼人的“广域构建”问题终于得到了彻底的解决。以下是the v3.3 release notes的摘录:

Functionality

Changes introduced by PEP 393 are the following:

  • Python now always supports the full range of Unicode codepoints, including non-BMP ones (i.e. from U+0000 to U+10FFFF). The distinction between narrow and wide builds no longer exists and Python now behaves like a wide build, even under Windows.
  • With the death of narrow builds, the problems specific to narrow builds have also been fixed, for example:
    • len() now always returns 1 for non-BMP characters, so len('\U0010FFFF') == 1;
    • surrogate pairs are not recombined in string literals, so '\uDBFF\uDFFF' != '\U0010FFFF';
    • indexing or slicing non-BMP characters returns the expected value, so '\U0010FFFF'[0] now returns '\U0010FFFF' and not '\uDBFF';
    • all other functions in the standard library now correctly handle non-BMP codepoints.
  • The value of sys.maxunicode is now always 1114111 (0x10FFFF in hexadecimal). The PyUnicode_GetMax() function still returns either 0xFFFF or 0x10FFFF for backward compatibility, and it should not be used with the new Unicode API (see issue 13054).
  • The ./configure flag --with-wide-unicode has been removed.

Python正则表达式的未来

与标准Python发行版的re库中当前可用的相比,Matthew Barnett’s ^{} module for both Python 2 and Python 3 alike在几乎所有可能的方面都要好得多,并且最终很可能会取代re。与您的问题特别相关的是,他的regex库在各个方面都远比现在的re库更兼容Perl。因为它是一个基础重写(如从头开始,而不是汉堡:),所以它是在考虑非ASCII的情况下编写的,而不是re

因此,regex库在处理问题的方式上更接近于UTS#18: Unicode Regular Expressions的(当前)建议。它满足或超过了UTS#18 Level 1的要求在大多数情况下,如果不是所有方面,通常必须使用ICU regex库或Perl本身,或者如果您特别勇敢,新的Java 7更新到它的regex,因为这也符合UTS#18的Level One requirements

除了满足那些一级需求(这些需求对于基本的Unicode支持是绝对必要的,但是Python当前的re库并不能满足这些需求之外,这个很棒的regex库还满足RL2.5命名字符(\N{...}))、RL2.2扩展Grapheme集群(\X)的二级需求,以及来自revision 14 of UTS#18的完整属性的新RL2.7。

Matthew的regex模块还执行Unicode casefolding,以便不区分大小写的匹配在Unicode上可靠地工作,re不工作。

下面不再是正确的,因为regex现在支持完整的Unicode casefolding,如Perl和Ruby。

One super‐tiny difference is that for now, Perl’s case‐insensitive patterns use full string‐oriented casefolds while his regex module still uses simple single‐char‐oriented casefolds, but this is something he’s looking into. It’s actually a very hard problem, one which apart from Perl, only Ruby even attempts.

在全casefolding下,这意味着(例如)"ß"在选择不区分大小写的匹配时,现在可以更正匹配项"SS""ss""ſſ""ſs"(等等)。(这在希腊语脚本中比拉丁语脚本中更为重要。)

另请参阅my third OSCON2011 talk中标题为Unicode支持Shootout:the Good,the Bad,and the(most)aucky的幻灯片或文档源代码,了解跨JavaScript、PHP、Go、Ruby、Python、Java和Perl的Unicode支持的一般问题。如果不能使用Perl正则表达式或者可能使用ICU正则表达式库(它没有命名的捕获,唉!),那么Matthew为Python编写的regex可能是最好的一张照片。


NᴏᴛᴀBᴇɴs.ᴠ.ᴘ。(=s'il vous plaît,et mème s'il ne vous plaît pas:)以下未经请求的非商业性非广告实际上是Python库作者放在这里的。:)

regex功能

Pythonregex库具有大量的超纯特性,其中一些特性在任何其他regex系统中都找不到。不管你是不是碰巧用它来做ess或其一流的Unicode支持。

本模块的一些突出特点是:

  • 可变宽度查找,这是regex引擎中非常少见的功能,当您真正需要它时却没有它,这非常令人沮丧。这很可能是regex中最常请求的特性。
  • 向后搜索,这样你就不必自己先反向搜索字符串。
  • 作用域为ismx类型的选项,因此(?i:foo)仅用于foo的casefold,而不用于overall,或者(?-i:foo)仅在foo上关闭它。这就是Perl的工作原理(或者可以)。
  • 基于编辑距离的模糊匹配(Udi-Manber的agrepglimpse也有)
  • 通过\L<list>插值隐式最短到最长排序命名列表
  • 元字符,只与单词的开头或结尾匹配,而不与单词的两边匹配(\m\M
  • 支持所有Unicode行分隔符(Java可以做到这一点,Perl也可以做到这一点,尽管Perl对每个RL1.6使用\R有些不情愿。
  • RL1.3对括号中的字符类执行全集操作(并集、交集、差分和对称差分),这比在Perl中获取要容易得多。
  • 允许像(\w+\s+)+这样的重复捕获组,在这里您可以获得第一个组的所有单独匹配项,而不仅仅是最后一个匹配项。(我相信C也会这么做。)
  • 一种更直接的方法来获取重叠的匹配,而不是在lookaheads中偷偷摸摸地捕获组。
  • 用于以后切片/子串操作的所有组的开始和结束位置,非常类似于Perl的@+@-数组。
  • branch-reset操作符通过(?|...|...|...|)按照Perl中的工作方式重置每个分支中的组编号。
  • 可以配置为让您的咖啡在早上等您。
  • 支持RL2.3中更复杂的单词边界。
  • 默认情况下采用Unicode字符串,并完全支持RL1.2a,以便\w\b\s,以及对Unicode的处理。
  • 支持图形的\X
  • 支持\G连续点断言。
  • 适用于64位生成(re只有32位索引)。
  • 支持多线程。

好吧,那就够炒作了。:)

又一个不错的备用Regex引擎

如果你是一个regex极客的话,最后一个值得关注的选择是对Russ Cox的很棒的RE2 libraryPython library bindings。它还支持本机Unicode,包括简单的基于字符的casefolding,与re不同的是,它显著地提供了Unicode常规类别和Unicode脚本字符属性,这两个属性是Unicode处理更简单类型最常需要的两个关键属性。

尽管RE2漏掉了一些Unicode特性,比如ICU、Perl和Python中的\N{...}命名字符支持,它具有极其严重的计算优势,使得它成为了regex引擎的首选,无论何时,只要您担心通过web查询等中的regex进行基于饥饿的拒绝服务攻击。它通过禁止反向引用来管理这一点,这会导致正则表达式不再是规则的,并有可能在时间和空间上发生超指数爆炸。

Re2的库绑定不仅适用于C/C++和Python,而且还适用于Perl,尤其是GO,在那里很快就会替换标准的正则表达式库。

相关问题 更多 >