将 Perl Regex 语句转换为 Python Regex



我需要将一些正则表达式从perl转换为python,但我对perl正则表达式不是很熟悉。

我有以下几点:

$x =~ s/([^"])(items+7[^0-9a-z"]*management(?:[^0-9a-z]{0,3}s)?s+discussions?s+ands+analysiss+ofs+(?:financials+conditions?s+|resultss+ofs+operations?)(?:s+ands+resultss+ofs+operations?|s+ands+financials+conditions?)?)/1#######ITEM7:2#######/gis;
$x =~ s/([^"])(items+7[^0-9a-z"]*a[^0-9a-z"]*(?:quantitatives+ands+(?:qualitative|qualification)s+disclosures?s+abouts+)?markets+risk)/1#######ITEM7A:2#######/gis;
$x =~ s/([^"])(items+8[^0-9a-z"]*.{0,40}financials+statements[^.])/1#######ITEM8:2#######/gis;
@X = (split /#######/, $x)

我相信s/等同于pythonre.split但我不确定/gis是做什么的。

另外,我也不确定这意味着什么:

(@M) = ($y =~ m/((?:d+:ITEM7 d+:d+ )+(?:d+:ITEM7A d+:d+ )*)(?:d+:ITEM8 d+:d+s*)+/g)

我将非常感谢您的帮助!

编辑:

只是另一个快速的问题,究竟是做什么的:

for($i = 0; $i < scalar(@X); ++$i) {
if($X[$i] =~ m/^(ITEM(?:7|7A|8)):(.*)$/s) {
$Z[$i] = $2; 
$Y[$i] = $i . ':' . $1; 
} else {   
$Z[$i] = $X[$i]; 
$Y[$i] = $i . ':' . length_in_words($X[$i]);  
}
}
sub length_in_words {
my $x = shift;
my @k;
return scalar(@k = $x =~ m/(S+)/sg);
}

首先,通过为该超长模式的组件设置变量,然后在模式本身中使用它们,整个事情可以写得更好。

实际上,这两种语言支持的所有基本正则表达式语法都是相同的,或者足够接近,因此我不会在这里列出[..]s的含义。需要翻译的是整体操作(运算符、函数等),以及使用的几个标志

  • 正则表达式组使用替换运算符$x =~ s/pattern/repl/,其中替换是在变量$x上(就地)完成的。 在python中,这是re.sub

  • Perl 正则表达式中/gis的尾随修饰符的意思是:查找并替换所有出现的模式 (/g),忽略大小写 (/i),并使.匹配任何内容 (/s),包括换行符。

    在python中,要替换模式的所有出现,只需省略count(或将其设置为零),这将是下面re.sub的第四个参数(在string和标志之间),而对于其他两个参数,有标志: IGNORECASE(或I)和DOTALL(或S)

我们总共有

import re
result = re.sub(pattern, replacement, string, flags=re.I|re.S)

它返回新字符串,与 Perl 的默认就地替换不同,因此如果您希望模拟给定的正则表达式,请re.sub分配回string

除了上面链接的参考perlreperlop之外,Perl 正则表达式的其他一些有用资源是教程 perlretut 和快速参考 perlreref,


这是一个更完整示例的第一个正则表达式。我想先在Perl方面重写它

# Opening "item", a phrase, and phrases with alternation
my $item   = qr/(items+7[^0-9a-z"]*management(?:[^0-9a-z]{0,3}s)?s+/;
my $phrase = qr/discussions?s+ands+analysiss+ofs+/;
my $pa1 = qr/(?:financials+conditions?s+|resultss+ofs+operations?)/;
my $pa2 = qr/(?:s+ands+resultss+ofs+operations?|s+ands+financials+conditions?)?)/
$x =~ s/([^"])$item$phrase$pa1$pa2/$1#######ITEM7:$2#######/gis;

我已经使用qr来构造一个适当的正则表达式模式(在精神上类似于Python中的re.compile对象),而在这种情况下,普通字符串也可以。

我已经用$1$2替换了长期过时的1和替换侧的2。 (1用作正则表达式匹配侧工作的反向引用。

在 Python 中,具有问题中给出的巨大模式

patt = re.compile("...", flags=re.I|re.S)
string = patt.sub(r"g<1>#######ITEM7:g<2>#######/", string)

或者,更好的是,如上所述的第一个形式子模式(省略号表示需要完成它们)

item   = "(items+..."
phrase = "discussions?..."
pa1    = "(?:financials..."
pa2    = "(?:s..."
patt = re.compile(item+phrase+pa1+pa2, flags=re.I|re.S)
string = patt.sub(r"g<1>#######ITEM7:g<2>#######/", string)

使用re.compile绝不是强制性的;re.sub(例如,直接在开头使用)通常是完全相同的。但我认为re.compile是代码组织的好工具(撇开效率问题不谈)。

如果你还没有使用Python 3,你需要re.compile才能使用标志。

据我所知,所有模式本身在 Python 中都是相同的,所以你可以简单地复制它。

示例:(?:[^0-9a-z]{0,3}s)?的工作方式如下

  • 非捕获(?: ... )对事物进行分组(但不存储任何内容),因此可以制作它......

  • 可选,(?: ... )?与最后?(匹配 0 或 1 次,整个事情)

  • 否定字符类[^0-9a-z]匹配除数字或小写字母以外的任何内容...

  • 0 到 3 次与[^0-9a-z]{0,3}(但不需要0,因为{3}的意思是一样的)

  • 最后s只是字面意思s

请注意,对于标志/i(re.I),上面的否定字符类排除了所有字母。


带有正则表达式的最后一个语句

my @M =  $y =~ m/(...)+/g;

匹配字符串中给定模式的所有出现次数(/g$y(匹配运算符m//绑定到$y=~运算符)并返回分配给数组@M的匹配列表。

在Perl中,匹配运算符可以返回1或空字符串(true/false)包含实际匹配的列表,具体取决于它所处的上下文。在这里,列表上下文是通过表达式$y =~ m/.../分配给数组这一事实强加给它的。

我删除了上面不需要的括号,并添加了变量的声明,my @M.我在那个长模式中看不到任何有趣的东西,所以我把它排除在外。

你可以在 Python 中通过 re.findall 的基本用法得到这个


问题的编辑。 代码

for($i = 0; $i < scalar(@X); ++$i)

遍历数组@X的索引,但更好(更好)的方法是

for my $i (0..$#X)

@X的最后一个索引和范围运算符n .. m使用语法$#X。 语法$X[$i]适用于位于索引$i的数组@X元素。 Perl 中的数组是从 0 开始的。

然后在循环内部有一个基于正则表达式匹配的简单条件

if ( $X[$i] =~ m/^(ITEM(?:7|7A|8)):(.*)$/s )

其中,此处m//匹配运算符返回1/''(true/false),位于标量上下文中(if语句的条件最终需要一个布尔值)。因此,如果存在匹配项,则if将获得一个非零数字并计算为 true,否则代码将下降到else

修饰符/s,也出现在替换正则表达式中,也使.匹配换行符,以便整个模式可以跨多行字符串中的行匹配。

在这两个if中 - 设置了else分支元素(@Z@Y),如果存在匹配,则使用正则表达式捕获的模式($1$2)。

最后,.是连接运算符,表达式$i . ':' . $1连接$i的值、文字:和(第一次捕获)$1length_in_words()是一个子例程。


编辑: 子例程length_in_words()现已添加到问题中。

简而言之:子例程接受一个字符串并返回其中的单词数。

移位从数组中删除第一个元素。默认情况下,它这样做是为了@_(在 sub 中时)带有函数参数的数组。$x输入字符串也是如此,输入字符串是用来调用函数的。

正则表达式匹配$x中的所有单词(/g修饰符下S+),并返回该列表,该列表分配给数组@k。然后scalar获取数组中的元素数,返回的内容。

恕我直言,正则表达式引擎实际上与python派生的PCRE相同 区别在于与结果相关的利用率/替换

s///g替换全局出现,将是 re.sub()s///" 表示 # 次 re.sub() 并指定 # 但是 re.sub() 返回一个新字符串,不会像在 perl 中那样修改其参数a =~ s///

使用i选项不区分大小写将是重新。忽略或重新。我
s单行,即整行同时
被视为一个模式空间 - 我承认我不知道这会在 Python 中

(@M) = ($y =~ m/((?:d+:ITEM7 d+:d+ )+(?:d+:ITEM7A d+:d+ )*)(?:d+:ITEM8 d+:d+s*)+/g)

恕我直言,简直是

@arr = $y =~/((?:\d+:ITEM7 \d+:\d+ )+(?:\d+:ITEM7A \d+:\d+ ))(?:\d+:

ITEM8 \d+:\d+\s)+/g

指示 perl:
将模式与变量包含的任何y匹配,并将所有后续结果放入数组arr@arr[0] 分配了第一个捕获的组,
@arr[1] 分配了第二个组,依此类推,最后一个是整个匹配,没有接触原始yvar 中的任何内容,在这种情况下只有 1 个捕获的组为 (?:) 不捕获任何内容。在全局事件时执行此操作,直到模式空间结束。

但是对于替换 - 假设情况略有不同:$b = $y =~ s/((?:d+:ITEM7 d+:d+ )+(?:d+:ITEM7A d+:d+ )*)(?:d+:ITEM8 d+:d+s*)+/TEST_1/g

将模式与y变量包含的任何内容进行匹配,并将后续结果替换为TEST_1(\1 旨在替换为第一个捕获组 ()),覆盖原始y变量,继续这样做,也将其设置为新的模式空间,分配布尔值 true,或 T 或 1 到bvar, 如果不成功,则按原样保留y,将布尔值分配给
falseb

最新更新