为什么表达式的顺序在 re.match 中很重要?
Why does the order of expressions matter in re.match?
我正在制作一个函数,它将接受“three()”或“{1 + 2}”之类的字符串并将它们放入标记列表中(例如:“three()”= [ "three", "(", ")"] 我使用 re.match 来帮助分隔字符串。
def lex(s):
# scan input string and return a list of its tokens
seq = []
patterns = (r"^(\t|\n|\r| )*(([a-z])*|[0-9]|\(|\)|\*|\/|)(\t|\n|\r| )*")
m = re.match(patterns,s)
while m != None:
if s == '':
break
seq.append(m.group(2))
s = s[len(m.group(0)):]
m = re.match(patterns,s)
return seq
如果字符串只是“三”,则此方法有效。但如果字符串包含“()”或任何符号,它就会留在 while 循环中。
但是当在它起作用的模式字符串中移动 ([a-z])* 时会发生一件有趣的事情。为什么会这样?
works: patterns = (r"^(\t|\n|\r| )*([0-9]|\(|\)|\*|\/|([a-z])*)(\t|\n|\r| )*")
Does not work: patterns = (r"^(\t|\n|\r| )*(([a-z])*|[0-9]|\(|\)|\*|\/)(\t|\n|\r| )*")
这个有点棘手,但问题出在这部分([a-z])*
。这匹配任何大小为 0(零)或更大的小写字母字符串。
如果你把这个序列放在最后,就像这里:
patterns = (r"^(\t|\n|\r| )*([0-9]|\(|\)|\*|\/|([a-z])*)(\t|\n|\r| )*")
正则表达式引擎将首先尝试其他匹配项,如果找到匹配项,就停止。只有当 none 的其他人匹配时,它才会尝试 ([a-z])*
并且由于 *
是 'greedy',它将匹配所有 three
,然后继续匹配 (
最后是 )
.
阅读有关如何测试完整表达式的解释 in the documentation(感谢 @kaya3)。
但是,如果您将该序列放在开头,如下所示:
patterns = (r"^(\t|\n|\r| )*(([a-z])*|[0-9]|\(|\)|\*|\/)(\t|\n|\r| )*")
它将首先尝试匹配它。它仍然很贪心,所以 three
仍然匹配。但是在下一次尝试中,它将尝试将 ([a-z])*
与剩余的 '()'
匹配 - 并且它 匹配 ,因为该字符串以零字母开头。
一直这样匹配,一直卡在循环里。您可以通过将 *
更改为 +
来修复它,只有在有 1 个或多个匹配项时才会匹配:
patterns = (r"^(\t|\n|\r| )*(([a-z])+|[0-9]|\(|\)|\*|\/)(\t|\n|\r| )*")
我正在制作一个函数,它将接受“three()”或“{1 + 2}”之类的字符串并将它们放入标记列表中(例如:“three()”= [ "three", "(", ")"] 我使用 re.match 来帮助分隔字符串。
def lex(s):
# scan input string and return a list of its tokens
seq = []
patterns = (r"^(\t|\n|\r| )*(([a-z])*|[0-9]|\(|\)|\*|\/|)(\t|\n|\r| )*")
m = re.match(patterns,s)
while m != None:
if s == '':
break
seq.append(m.group(2))
s = s[len(m.group(0)):]
m = re.match(patterns,s)
return seq
如果字符串只是“三”,则此方法有效。但如果字符串包含“()”或任何符号,它就会留在 while 循环中。 但是当在它起作用的模式字符串中移动 ([a-z])* 时会发生一件有趣的事情。为什么会这样?
works: patterns = (r"^(\t|\n|\r| )*([0-9]|\(|\)|\*|\/|([a-z])*)(\t|\n|\r| )*")
Does not work: patterns = (r"^(\t|\n|\r| )*(([a-z])*|[0-9]|\(|\)|\*|\/)(\t|\n|\r| )*")
这个有点棘手,但问题出在这部分([a-z])*
。这匹配任何大小为 0(零)或更大的小写字母字符串。
如果你把这个序列放在最后,就像这里:
patterns = (r"^(\t|\n|\r| )*([0-9]|\(|\)|\*|\/|([a-z])*)(\t|\n|\r| )*")
正则表达式引擎将首先尝试其他匹配项,如果找到匹配项,就停止。只有当 none 的其他人匹配时,它才会尝试 ([a-z])*
并且由于 *
是 'greedy',它将匹配所有 three
,然后继续匹配 (
最后是 )
.
阅读有关如何测试完整表达式的解释 in the documentation(感谢 @kaya3)。
但是,如果您将该序列放在开头,如下所示:
patterns = (r"^(\t|\n|\r| )*(([a-z])*|[0-9]|\(|\)|\*|\/)(\t|\n|\r| )*")
它将首先尝试匹配它。它仍然很贪心,所以 three
仍然匹配。但是在下一次尝试中,它将尝试将 ([a-z])*
与剩余的 '()'
匹配 - 并且它 匹配 ,因为该字符串以零字母开头。
一直这样匹配,一直卡在循环里。您可以通过将 *
更改为 +
来修复它,只有在有 1 个或多个匹配项时才会匹配:
patterns = (r"^(\t|\n|\r| )*(([a-z])+|[0-9]|\(|\)|\*|\/)(\t|\n|\r| )*")