我需要将一些正则表达式从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)
我相信
s/等同于python
re.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的含义。需要转换的是整体操作(运算符,功能等)以及所使用的几个标志
正则表达式组使用替换operator,$x =~ s/pattern/repl/,从而在变量$x上(以及就地)进行替换。在python中是re.sub
Perl正则表达式中的尾随modifiers /gis表示:查找并替换所有出现的模式(/g),忽略大小写(/i),并使.匹配任何内容(/s),包括新队。
在python中,要替换所有出现的模式,只需省略count(或将其设置为零),这将是下面re.sub中的第四个参数(在string和标志之间),而对于另外两个有标志:
IGNORECASE (or I)和DOTALL (or S)
我们总共有
import re
result = re.sub(pattern, replacement, string, flags=re.I|re.S)
它返回新字符串,这与Perl的默认就地替换不同,因此,如果要模拟给定的正则表达式,请将
re.sub分配回
string。
除了上面链接的参考
perlre和
perlop外,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;
我已经使用 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 = "(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)
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
请注意,带有标志
/i(
re.I)的上述否定字符类排除了所有字母。
最后一个带有正则表达式的语句
my @M = $y =~ m/(...)+/g;
匹配字符串
/g中给定模式的所有出现(
$y)
( match operator
m//被
$y operator绑定到
=~)并返回分配给数组
@M的匹配项列表。
在Perl中,匹配运算符可以返回
1或空字符串(true / false)或具有实际匹配项的列表,具体取决于它所在的
context。在这里,列表上下文是由表达式来施加的
$y =~ m/.../
assigns to an array。
我已经删除了上面不需要的括号,并添加了变量
my @M的声明。在这种长模式下,我看不到任何有趣的东西,因此我将其省略。
您可以在Python中使用 re.findall的基本用法
问题的编辑。代码
for($i = 0; $i < scalar(@X); ++$i)
遍历数组
@X的索引,但是更好(更好)的方法是
for my $i (0..$#X)
对
$#X的最后一个索引和范围运算符
@X使用语法
n .. m。语法
$X[$i]用于数组
@X的元素,该元素位于索引
$i。 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,文字
:和(第一个捕获)
$1的值连接起来。
length_in_words()是一个子例程。
编辑:子程序
length_in_words()现在已添加到问题中。
简而言之:子例程接受一个字符串并返回其中的单词数。
shift从数组中删除第一个元素。默认情况下,它将对具有函数参数的数组
@_(在子目录中)执行此操作。因此,
$x是输入字符串,即使用该函数调用的内容。
正则表达式匹配
\S+中的所有单词(
/g修饰符下的
$x)并返回该列表,该列表已分配给数组
@k。然后
scalar接受数组中元素的数量,返回什么。
