如何在Python中使用带有命名组的正则表达式子模式?

时间:2014-01-13 17:12:17

标签: python regex perl

我正在将一个正则表达式的脚本从Perl翻译成Python,我遇到了正则表达式子模式的问题。

在Perl中,如果按预期编写以下工作,即写入字符串“OK”。我从来没有多想过,但看起来Perl知道那些是不同的组,尽管它们有相同的名称。

my $ident  = qr{ (?<guill> ['"`]? ) [a-zA-Z_] \w* \g{guill} }x;
my $idents = qr{ (?: $ident \s* , \s* )* $ident }x;
my $test   =  q{'test', "test"};

if ($test =~ $idents) {
    say 'OK';
}

我发现除了在编译为正则表达式模式之前将字符串置于字符串之外,我没有办法在Python中的模式中插入子模式,所以我将我的Perl代码翻译为:

ident  = r"(?P<guill> ['\"`]? ) [a-zA-Z_] \w* (P=guill)"
idents = r"(?: " + ident + r" \s* , \s* )* " + ident
test   = "'test', \"test\""

if re.match( idents, test, re.VERBOSE ):
    print "OK"

毫不奇怪,这甚至都没有编译,因为Python抱怨“将组名重新定义为'guill'为第3组”。我尝试了Perlish方法和re.compile'd ident,但后来拒绝将字符串与模式对象连接起来。

Python的实现方式是什么?

2 个答案:

答案 0 :(得分:2)

这可以使用真正的正则表达式来完成。

ident0 = r"[a-zA-Z_] \w*"
ident1 = r"' [a-zA-Z_] \w* '"
ident2 = r"\" [a-zA-Z_] \w* \""
ident3 = r"` [a-zA-Z_] \w* `"
ident  = "(?:" + ident0 + "|" + ident1 + "|" + ident2 + "|" + ident3 + ")"

答案 1 :(得分:1)

与@ ikegami的回答几乎相同,但没有identN名称(通常表明列表是更好的选择),还有更多Pythonic '|'.join

subidents = [
    r"[a-zA-Z_] \w*",
    r"'[a-zA-Z_] \w* '",
    r"\"[a-zA-Z_] \w* \"",
    r"`[a-zA-Z_] \w* `",
    ]
ident = "(?:%s)" % '|'.join(subidents)

现在,您可以将您的子事件列表扩展为更多。

专业提示:当您可能在以后添加更多项目时,在最后一个列表项目后添加一个尾随逗号 - 在比较版本时减少无关的更改行。