Python正则表达式:贪婪模式返回多个空匹配

Sch*_*mer 4 python regex pattern-matching

这种模式只是简单地抓取字符串中的所有内容,直到数据中的第一个潜在句子边界:

[^\.?!\r\n]*
Run Code Online (Sandbox Code Playgroud)

输出:

>>> pattern = re.compile(r"([^\.?!\r\n]*)")
>>> matches = pattern.findall("Australians go hard!!!") # Actual source snippet, not a personal comment about Australians. :-)
>>> print matches
['Australians go hard', '', '', '', '']
Run Code Online (Sandbox Code Playgroud)

来自 Python 文档:

re.findall(模式,字符串,标志= 0)

以字符串列表的形式返回字符串中模式的所有非重叠匹配项。从左到右扫描字符串,并按找到的顺序返回匹配项。如果模式中存在一个或多个组,则返回组列表;如果模式有多个组,这将是一个元组列表。空匹配项包含在结果中,除非它们触及另一个匹配项的开头。

现在,如果从左到右扫描字符串并且 * 运算符是贪婪的,那么返回的第一个匹配是整个字符串直到感叹号是完全合理的。但是,在消耗完那部分之后,我看不到该模式如何精确地产生四次空匹配,大概是通过在“d”之后向左扫描字符串。我确实理解 * 运算符意味着此模式可以匹配空字符串,我只是不知道它会如何在字母的尾随“d”和前导“!”之间多次执行此操作。的标点符号。

添加 ^ 锚点具有以下效果:

>>> pattern = re.compile(r"^([^\.?!\r\n]*)")
>>> matches = pattern.findall("Australians go hard!!!")
>>> print matches
['Australians go hard']
Run Code Online (Sandbox Code Playgroud)

由于这消除了空字符串匹配,它似乎表明所述空匹配发生在字符串的前导“A”之前。但这似乎与按照找到的顺序返回匹配项的文档相矛盾(前导“A”之前的匹配项应该排在第一位),而且恰好四个空匹配项让我感到困惑。

rch*_*ang 6

*量词允许捕获长度为零的子串的图案。在您的原始代码版本中(^前面没有锚点),额外的匹配项是:

  • 结尾之间的零长度字符串 hard和第一个!
  • 第一个和第二个之间的零长度字符串 !
  • 第二个和第三个之间的零长度字符串 !
  • 第三个!和文本结尾之间的零长度字符串

如果你喜欢这里,你可以进一步切片/切块。

^现在将该锚点添加到前面可以确保只有一个子字符串可以匹配模式,因为输入文本的开头恰好出现一次。