Python 在 if 语句中使用正则表达式匹配对象,然后访问像 Perl 这样的捕获组

noa*_*oah 3 python regex perl

是否可以在 Python 中执行类似以下 Perl 代码的操作?据我所知,答案是否定的,但我想我会仔细检查一下。

我想在 Python 中复制的 Perl 代码:

#!/usr/bin/perl

my $line = "hello1234world";

if($line=~/hello(.*)world/) {
  print($1);
}
#prints 1234    
Run Code Online (Sandbox Code Playgroud)

以下是我能想到的最接近的风格,但在运行时我(显然)收到以下错误:

import re
line = "hello1234world"

if matchObj = re.match(r'hello(.*)world',line):
    print(matchObj.group(1))

#error: if matchObj = re.match(r'hello(.*)world',line):
#error:             ^
#error: SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

以下是我能想到的最好的工作代码:

import re
line = "hello1234world"

matchObj = re.match(r'hello(.*)world',line)

if matchObj:
    print(matchObj.group(1))
#prints 1234
Run Code Online (Sandbox Code Playgroud)

如果可能的话,我真的很想避免为变量声明和 if 语句单独一行。

zdi*_*dim 5

可以只打印(假设的)捕获并使用异常来处理group调用方法时的情况None,当没有匹配时返回。如果匹配失败时确实无事可做,则通过With Statement Context Manager (3.4+) 一行

from contextlib import suppress

with suppress(Exception):
    print( re.match(r'hello(.*)world', line).group(1) )
Run Code Online (Sandbox Code Playgroud)

为避免忽略这里几乎肯定不应忽略的异常,例如SystemExitand KeyboardInterrupt,请使用

with suppress(BaseException):
    ...
Run Code Online (Sandbox Code Playgroud)

正如所要求的那样,这现在相当紧凑,并且它的行为符合要求。仅使用异常来缩短代码可能会被认为是误导,但也许会有进一步的用途。

正如评论中提到的,从 3.8 开始就有了赋值表达式

if match := re.match(r'hello(.*)world', line):
    print( match.group(1) )
Run Code Online (Sandbox Code Playgroud)

这几乎直接匹配激励语义。然而,这个较新的特性引起了一些敏感的讨论,而仅仅使用它来缩短代码可能会混淆和误导,因为它不同于预期的 pythonic 方法。

我想补充一点,我建议不要担心额外的几行代码,特别是要避免模仿其他语言的样式和程序流程。使用手头语言固有的样式和习语具有巨大的价值。