我需要将一些正则表达式从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
。
除了上面链接的参考perlre
和perlop
之外,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
的值、文字:
和(第一次捕获)$1
。length_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] 分配了第二个组,依此类推,最后一个是整个匹配,没有接触原始y
var 中的任何内容,在这种情况下只有 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 到b
var, 如果不成功,则按原样保留y
,将布尔值分配给
falseb