Python中是否有任何组合编译正则表达式的机制?
我知道可以通过.pattern从现有模式对象中提取plain-old-string 属性来编译新表达式.但这在几个方面失败了.例如:
import re
first = re.compile(r"(hello?\s*)")
# one-two-three or one/two/three - but not one-two/three or one/two-three
second = re.compile(r"one(?P<r1>[-/])two(?P=r1)three", re.IGNORECASE)
# Incorrect - back-reference \1 would refer to the wrong capturing group now,
# and we get an error "redefinition of group name 'r1' as group 3; was
# group 2 at position 47" for the `(?P)` group.
# Result is also now case-sensitive, unlike 'second' which is IGNORECASE
both = re.compile(first.pattern + second.pattern + second.pattern)
Run Code Online (Sandbox Code Playgroud)
我正在寻找的结果在Perl中是可以实现的:
$first = qr{(hello?\s*)};
# one-two-three or one/two/three - but not one-two/three or one/two-three
$second = qr{one([-/])two\g{-1}three}i;
$both = qr{$first$second$second};
Run Code Online (Sandbox Code Playgroud)
测试显示结果:
test($second, "...one-two-three..."); # Matches
test($both, "...hello one-two-THREEone-two-three..."); # Matches
test($both, "...hellone/Two/ThreeONE-TWO-THREE..."); # Matches
test($both, "...HELLO one/Two/ThreeONE-TWO-THREE..."); # No match
sub test {
my ($pat, $str) = @_;
print $str =~ $pat ? "Matches\n" : "No match\n";
}
Run Code Online (Sandbox Code Playgroud)
是否有某个库可以在Python中使用这个用例?或者我在某个地方缺少一个内置功能?
(注意 - 上面的Perl正则表达式中的一个非常有用的特性是\g{-1},它明确地引用了前一个捕获组,因此当我尝试编译组合表达式时,没有Python抱怨的类型的冲突.我没有'在Python世界的任何地方都可以看到,不确定是否有一个我没有想过的替代方案.)
Jas*_*ont -1
我不是 Perl 专家,但看起来你并没有在比较苹果与苹果。您在 python 中使用命名捕获组,但我在 perl 示例中没有看到任何命名捕获组。这会导致您提到的错误,因为这
both = re.compile(first.pattern + second.pattern + second.pattern)
Run Code Online (Sandbox Code Playgroud)
尝试创建两个名为的捕获组r1
例如,如果您使用下面的正则表达式,然后尝试按名称访问 group_one,您会得到“某些文本”之前还是之后的数字?
# Not actually a valid regex
r'(?P<group_one>[0-9]*)some text(?P<group_one>[0-9]*)'
Run Code Online (Sandbox Code Playgroud)
解决方案1
一个简单的解决方案可能是从捕获组中删除名称。还将 re.IGNORECASE 添加到both. 下面的代码有效,尽管我不确定生成的正则表达式模式是否与您希望它匹配的内容相匹配。
first = re.compile(r"(hello?\s*)")
second = re.compile(r"one([-/])two([-/])three", re.IGNORECASE)
both = re.compile(first.pattern + second.pattern + second.pattern, re.IGNORECASE)
Run Code Online (Sandbox Code Playgroud)
解决方案2
我可能会做的是将单独的正则表达式定义为字符串,然后您可以根据需要组合它们。
pattern1 = r"(hello?\s*)"
pattern2 = r"one([-/])two([-/])three"
first = re.compile(pattern1, re.IGNORECASE)
second = re.compile(pattern2, re.IGNORECASE)
both = re.compile(r"{}{}{}".format(pattern1, pattern2, pattern2), re.IGNORECASE)
Run Code Online (Sandbox Code Playgroud)
或者更好的是,对于这个特定的示例,不要重复pattern2两次,只需考虑它将在正则表达式中重复的事实:
both = re.compile("{}({}){{2}}".format(pattern1, pattern2), re.IGNORECASE)
Run Code Online (Sandbox Code Playgroud)
它为您提供以下正则表达式:
r'(hello?\s*)(one([-/])two([-/])three){2}'
Run Code Online (Sandbox Code Playgroud)