regex while循环中的赋值表达式

lf3rwulv  于 2023-06-25  发布在  其他
关注(0)|答案(2)|浏览(98)
m = re.match(pattern, text)
while m := p.search(text, m.end()):
    # do with match

m.end()是否引用上一个匹配m,以便从上一个匹配的末尾开始搜索?我读了PEP-572,其中有一节专门讨论了正则表达式匹配,但没有涉及while循环。我知道m在循环体中是可用的,这不是这里的问题。

kg7wmglp

kg7wmglp1#

这段代码假设文本总是以匹配开始,否则,while原因将引发类型错误,因为re.match总是试图在开始时匹配,而不像re.search将搜索整个字符串(当然,除非您使用锚)。
所以是的,它基本上从最后一个匹配位置的末尾开始搜索,找到每个后续的非重叠匹配。你可以看到它是这样发生的:

>>> import re
>>> text = "foo some other stuff foo again foo foofofoo"
>>> p = re.compile("foo")
>>> m = p.match(s) # assumes it always matches at the beginning
>>> while print(m) or (m:= p.search(s, m.end())):
...     pass
...
<re.Match object; span=(0, 3), match='foo'>
<re.Match object; span=(21, 24), match='foo'>
<re.Match object; span=(31, 34), match='foo'>
<re.Match object; span=(35, 38), match='foo'>
<re.Match object; span=(40, 43), match='foo'>

因此while-loop的实际主体只能访问从第二个匹配开始的每个匹配。
注意,在本例中,您可能只想使用.finditer和for循环

>>> for m in p.finditer(text):
...     print(m)
...
<re.Match object; span=(0, 3), match='foo'>
<re.Match object; span=(21, 24), match='foo'>
<re.Match object; span=(31, 34), match='foo'>
<re.Match object; span=(35, 38), match='foo'>
<re.Match object; span=(40, 43), match='foo'>

除非主体正在更新m。注意,在这种情况下,for循环 * 将 * 访问第一个匹配,这与while循环的主体不同。如果你想跳过第一个,你总是可以这样做:

>>> it = p.finditer(text)
>>> next(it)
<re.Match object; span=(0, 3), match='foo'>
>>> for m in it:
...     print(m)
...
<re.Match object; span=(21, 24), match='foo'>
<re.Match object; span=(31, 34), match='foo'>
<re.Match object; span=(35, 38), match='foo'>
<re.Match object; span=(40, 43), match
1u4esq0p

1u4esq0p2#

我做了一个小实验,证明了我的追求。

def do(x):
    print(f'x in do = {x}')
    return (x + 1) if x < 5 else None
    
x = 0
while (x := do(x)) is not None:
    print(f'x in while = {x}')

输出:

x in do = 0
x in while = 1
x in do = 1
x in while = 2
x in do = 2
x in while = 3
x in do = 3
x in while = 4
x in do = 4
x in while = 5
x in do = 5

因此,我的问题的答案是“是的,即使在主体退出之后,变量的前一个值也可用于while循环”。实际上,就像一个常规变量一样,赋值变量从定义开始就在函数的其余部分的作用域中。

相关问题