当前位置: 首页 > 面试题库 >

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

许正平
2023-03-14
问题内容

我必须在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模块可以解析这种字符串吗?


问题答案:

Python如何处理模式和字符串中的非ASCII或未能处理非ASCII时,确实存在一些细微的问题。更糟糕的是,这些差异不仅取决于您使用的是哪个版本的Python,还取决于您是否拥有“广泛的构建”。

通常,当您处理Unicode时, 构建较宽的Python 3效果最佳, 而构建较窄的Python 2效果最差,但与Perl正则表达式 相对于
Unicode的工作方式相比,所有组合仍然相差甚远。如果要在Python中查找ᴘᴄʀᴇ模式,则可能需要比其旧re模块更进一步。

只要您使用足够高级的Python版本,就可以 彻底
解决
所有令人烦恼的“广泛构建”问题。这是v3.3发行说明的摘录:

功能性

PEP 393引入的更改如下:

  • Python现在始终支持所有Unicode代码点,包括非BMP代码点(即,从U + 0000到U +
    10FFFF)。窄和宽版本之间的区别不再存在,并且即使在Windows下,Python现在也像宽版本一样。
  • 随着狭窄版本的终止,狭窄版本所特有的问题也已修复,例如:
    • len()现在对于非BMP字符始终返回1,因此len('\U0010FFFF') == 1
    • 代理对不会在字符串文字中重组,因此'\uDBFF\uDFFF' != '\U0010FFFF';;
    • 索引或切片非BMP字符将返回期望值,因此'\U0010FFFF'[0]现在返回,'\U0010FFFF'而不是'\uDBFF'
    • 现在,标准库中的所有其他函数都可以正确处理非BMP代码点。
      * 现在的值sys.maxunicode始终为1114111(十六进制为0x10FFFF)。PyUnicode_GetMax()为了向后兼容,该函数仍返回0xFFFF或0x10FFFF,并且不应与新的Unicode
      API一起使用(请参见问题13054)。
  • The ./configure标志--with-wide-unicode已被删除。

Python正则表达式的未来

与标准Python发行版re库中当前可用的库相比,Matthew Barnett的regex同时适用于Python 2和Python
3的模块在几乎所有可能的方式上都好得多,并且会re最终被替换。与您的问题特别相关的是,他的regex库在各个方面都比现在更加强大(
即与 Perl兼容
得多re),这将使您更容易将Perl正则表达式移植到Python。因为它是完全重写(例如,从头开始,而不是在汉堡包中),所以它是在考虑非ASCII的情况下写的,而re不是这样。

regex因此,该库在如何处理事物方面更严格地遵循UTS#18(Unicode正则表达式)的(当前)建议。它在大多数情况下(即使不是全部)都
达到或超过了UTS#18 Level 1的要求 ,这通常是您必须使用ICU
regex库或Perl本身的东西–或者,如果您特别有胆量,则对它的正则表达式进行新的Java
7更新,例如也符合UTS#18的一级要求。

除了满足那些对基本Unicode支持绝对是必不可少的,但
Python当前re库不能regex满足的第一级要求之外

该强大的库还满足了RL2.5命名字符(\N{...})),RL2.2扩展字素的第二级要求。集群(\X),以及来自UTS#18修订版14的新的RL2.7,关于完全属性。

Matthew的regex模块还进行Unicode大小写折叠,因此区分大小写的匹配在Unicode上可靠地起作用, Unicode
则不然。 re

以下不再是正确的,因为regex现在支持完整的Unicode大小写折叠,例如Perl和Ruby。

一个非常小的区别是,目前,Perl的不区分大小写的模式使用完整的面向字符串的大小写折叠,而他的 regex模块仍使用简单的面向单个字符的大小写折叠,但这是他正在研究的问题。这实际上是一个非常棘手的问题,除了Perl之外,甚至只有Ruby都会尝试。

下充分casefolding,这意味着(例如)
"ß"现在是正确的匹配"SS""ss""ſſ""ſs"(等)当选择不区分大小写匹配。(这在希腊语中比在拉丁语中更重要。)

另请参阅我第三次OSCON2011演讲中的幻灯片或doc源代码,标题为
_“ Unicode支持大战:好,坏和(主要是)丑陋
”,_以获取有关JavaScript,PHP,Go,Ruby,Python,Java的Unicode支持的一般问题。和Perl。如果不能使用Perl正则表达式或ICU正则表达式库(可惜没有命名捕获),那么Matthew的regexPython可能就是您的最佳选择。

NᴏᴛᴀBᴇɴᴇs.ᴠ.ᴘ。(= s’il vousplaît等) :Python库的作者实际上 并未
在下面放置未经请求的非商业性非广告regex。:)

regex功能

Pythonregex库具有 超精巧的功能
,其中一些在其他正则表达式系统中找不到。无论您是偶然使用它来获得它的坚固性还是出色的Unicode支持,这些都非常值得一试。

该模块感兴趣的一些杰出功能包括:

  • 可变宽度向后看 ,这是一个功能,在正则表达式引擎中很少见,并且在您真正想要它时非常沮丧。这很可能是正则表达式中最常请求的功能。
  • 向后搜索,因此您不必自己先反转字符串。
  • 作用域ismx类型选项,以便(?i:foo)仅对foo进行大小写折叠,而不对整个字体进行折叠,或者(?-i:foo)仅对foo对其进行关闭。这就是Perl(或可以)的工作方式。
  • 基于编辑距离模糊匹配(这迪·曼伯的agrepglimpse也有)
  • 通过\L<list>插值隐式最短到最长排序的命名列表
  • 元字符只有一个单词的开始或仅结束特别地匹配,而不是任一侧(\m\M
  • 所有Unicode行分隔符支持(Java可以做到这一点,如Perl中尽管有几分勉强\R每RL1.6。
  • 根据RL1.3在括号中的字符类上进行全套运算(并集,交集,差和对称差),这比在Perl中轻松进行得多。
  • 允许重复捕获组,例如(\w+\s+)+您可以在其中获得第一个组的所有单独匹配,而不仅仅是最后一个匹配。(我相信C#也可以这样做。)
  • 与前行中的偷偷摸摸的捕获组相比,这是一种更为直接的重叠比赛方式。
  • 所有组的开始和结束位置,以便以后进行切片/子字符串操作,这与Perl@+@-数组非常相似。
  • 分支重置操作符通过(?|...|...|...|)其在Perl中的工作方式重置每个分支中的组编号。
  • 可以配置为让咖啡在早上等您。
  • 支持RL2.3中更复杂的单词边界。
  • 默认情况下,假设Unicode字符串,并完全支持RL1.2a让\w\b\s,而这些工作对Unicode的。
  • 支持字素\X
  • 支持\G连续点声明。
  • 对于64位版本(re仅具有32位索引)可以正常工作。
  • 支持多线程

好的,这已经足够炒作了。:)

另一个优良的替代正则表达式引擎

如果您是正则表达式怪胎,那么值得一看的最后一个替代方法是将Python库绑定到Russ
Cox出色的RE2库。它还本地支持Unicode,包括简单的基于字符的大小写折叠,并且与之不同的re是,它同时提供了Unicode常规类别和Unicode脚本字符属性,这是更简单的Unicode处理最常需要的两个关键属性。

尽管RE2错过了一些Unicode特性,例如\N{...}ICU,Perl和Python中的命名字符支持,但是RE2具有非常重要的计算优势,当您担心基于饥饿的拒绝服务时,它便成为
了正则表达式引擎的首选
通过Web查询等中的正则表达式进行攻击。它通过禁止反向引用来管理此问题,这会导致正则表达式停止正常运行,并有可能在时间和空间上发生超指数爆炸。

RE2的库绑定不仅适用于C / C ++和Python,还适用于Perl,尤其是Go(适用于Go),后者打算很快替换那里的标准正则表达式库。



 类似资料:
  • 主要内容:匹配操作符,实例,正则表达式变量,实例,替换操作符,实例,转化操作符,实例,更多正则表达式规则正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。 Perl语言的正则表达式功能非常强大,基本上是常用语言中最强大的,很多语言设计正则式支持的时候都参考Perl的正则表达式。 Perl的正则表达式的三种形式,分别是匹配,替换和转化: 匹配:m/ /(还可以简写为/ /,略去

  • 正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。 Perl语言的正则表达式功能非常强大,基本上是常用语言中最强大的,很多语言设计正则式支持的时候都参考Perl的正则表达式。 Perl的正则表达式的三种形式,分别是匹配,替换和转化: 匹配:m//(还可以简写为//,略去m) 替

  • 问题内容: 两种语言都声称使用Perl样式正则表达式。如果我使用一种语言测试正则表达式的有效性,那么它是否可以在另一种语言中工作?正则表达式语法在哪些方面有所不同? 这里的用例是一个C#(.NET)UI,它与最终的Java后端实现进行对话,该实现将使用正则表达式来匹配数据。 请注意,我只需要担心匹配,而不必担心提取匹配数据的某些部分。 问题答案: 有很多差异。 角色类 人物类减法 .NET 是(2

  • 我目前正在尝试创建一个日志解析器,它从一个输入文件(a.log)中获取以下格式的一系列ping报告:(194.12.224.34中的64字节:icmp_seq=1 ttl=47 time=66.7 ms)并构建一个输出文件(a.csv)。 经过多次尝试,我发现了下面的错误。我的同事给了我他的代码(如下),虽然写得不同,但本质上是一样的。他的代码给出了同样的错误,尽管他的代码在同一个任务中正常工作。

  • 序:世界上信息非常多,而我们关注的信息有限。假如我们希望只提取出关注的数据,此时可以通过一些表达式进行提取,正则表达式就是其中一种进行数据筛选的表达式。 正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。 正则表达式通常被用来匹配、检索、替换和分割那些符合某个模式(规则)的文本。 Python 自1.5版本起

  • 是否可以按任意顺序定义嵌套的正则表达式? 以下程序按预期工作: 如果交换前两行,编译器将产生错误。 有没有办法覆盖这个限制(不使用)?