将Perl Regex语句转换为Python Regex

Put*_*lls 1 python regex perl

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

我有以下几点:

$x =~ s/([^\"])(item\s+7[^0-9a-z\"]*management(?:[^0-9a-z]{0,3}s)?\s+discussions?\s+and\s+analysis\s+of\s+(?:financial\s+conditions?\s+|results\s+of\s+operations?)(?:\s+and\s+results\s+of\s+operations?|\s+and\s+financial\s+conditions?)?)/\1#######ITEM7:\2#######/gis;

$x =~ s/([^\"])(item\s+7[^0-9a-z\"]*a[^0-9a-z\"]*(?:quantitative\s+and\s+(?:qualitative|qualification)\s+disclosures?\s+about\s+)?market\s+risk)/\1#######ITEM7A:\2#######/gis;

$x =~ s/([^\"])(item\s+8[^0-9a-z\"]*.{0,40}financial\s+statements[^\.])/\1#######ITEM8:\2#######/gis;

@X = (split /\#\#\#\#\#\#\#/, $x)
Run Code Online (Sandbox Code Playgroud)

我相信这s/等效于python,re.split但是我不确定是什么/gis

另外,我也不知道这意味着什么:

(@M) = ($y =~ m/((?:\d+:ITEM7 \d+:\d+ )+(?:\d+:ITEM7A \d+:\d+ )*)(?:\d+:ITEM8 \d+:\d+\s*)+/g)
Run Code Online (Sandbox Code Playgroud)

我将不胜感激帮助!

编辑:

另一个简单的问题是:

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);
}
Run Code Online (Sandbox Code Playgroud)

zdi*_*dim 6

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

实际上所有的在这两个语言的支持的基本正则表达式的语法是相同的,或足够接近,这样我就不一一列举在这里什么[..]\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)
Run Code Online (Sandbox Code Playgroud)

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

除了参考资料perlreperlop上面链接的以外,Perl regex的其他有用资源还有教程perlretut和快速参考perlreref


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

# Opening "item", a phrase, and phrases with alternation
my $item   = qr/(item\s+7[^0-9a-z\"]*management(?:[^0-9a-z]{0,3}s)?\s+/;
my $phrase = qr/discussions?\s+and\s+analysis\s+of\s+/;
my $pa1 = qr/(?:financial\s+conditions?\s+|results\s+of\s+operations?)/;
my $pa2 = qr/(?:\s+and\s+results\s+of\s+operations?|\s+and\s+financial\s+conditions?)?)/

$x =~ s/([^\"])$item$phrase$pa1$pa2/$1#######ITEM7:$2#######/gis;
Run Code Online (Sandbox Code Playgroud)

我已经使用qr构造了适当的regex模式(本质上re.compile与Python中的对象类似),而在这种情况下,使用普通字符串也可以。

我把它换成了长已经过时\1,并\2通过更换侧$1$2。(\1用作正则表达式匹配侧中工作的反向引用。)

在Python中,使用问题中给出的巨大模式

patt = re.compile("...", flags=re.I|re.S)

string = patt.sub(r"\g<1>#######ITEM7:\g<2>#######/", string)
Run Code Online (Sandbox Code Playgroud)

或者,更好的是使用上述第一种形式的子模式(省略号表示需要完成)

item   = "(item\s+..."
phrase = "discussions?..."
pa1    = "(?:financial\s..."
pa2    = "(?:\s..."

patt = re.compile(item+phrase+pa1+pa2, flags=re.I|re.S)

string = patt.sub(r"\g<1>#######ITEM7:\g<2>#######/", string)
Run Code Online (Sandbox Code Playgroud)

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

如果您还没有使用Python 3,则需要re.compile使用标志。

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

一个例子:(?:[^0-9a-z]{0,3}s)?如下

  • 非捕获(?: ... )将事物分组(但不存储任何事物),因此可以做到这一点...

  • 可选(?: ... )?,最后一个?(在整个过程中匹配0或1次)

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

  • 零到三连倍[^0-9a-z]{0,3}(但没有必要0{3}装置相同)

  • s到底仅仅是文字字符s

请注意,带有标志/ire.I)的上述否定字符类排除了所有字母。


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

my @M =  $y =~ m/(...)+/g;
Run Code Online (Sandbox Code Playgroud)

匹配/g字符串中给定模式的所有匹配项()$ymatch运算符m//$y=~operator绑定),并返回分配给array的匹配项列表@M

在Perl匹配操作符可以返回1或空字符串(真/假) 与实际的比赛,这取决于一个列表上下文它是在这里的列表环境是由事实强加于它,表达$y =~ m/.../ 对阵列

我删除了上面不需要的括号,并添加了变量的声明my @M。在这种长模式下,我看不到任何有趣的东西,因此我将其省略。

您可以使用re.findall的基本用法在Python中获得此功能


问题的编辑。   代码

for($i = 0; $i < scalar(@X); ++$i)
Run Code Online (Sandbox Code Playgroud)

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

for my $i (0..$#X)
Run Code Online (Sandbox Code Playgroud)

使用和范围运算符$#X的最后一个索引的语法。语法适用于位于index处的array元素。Perl中的数组基于0。@Xn .. m$X[$i]@X$i

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

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

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

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

在这两种if- else分支又其它阵列的元素被设置(@Z@Y),并且如果有一个匹配,则使用(由正则表达式所捕获的图案$1$2)。

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


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

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

移位从数组中删除第一个元素。默认情况下,它对@_带有函数参数的数组(在子目录中)执行此操作。$x输入字符串也是如此,该函数使用了什么。

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