Python 正则表达式为最后一个匹配的字符返回额外的捕获组
Python regular expression returning extra capture group for last character matched
我正在尝试创建一个正则表达式,它将接受字符串并将它们分成三组:(1) 字符串开头的特定单词列表中的任何一个。 (2) 字符串末尾的特定单词列表中的任何一个。 (3) 这两场比赛之间的所有 letters/whitespace。
作为示例,我将使用以下两个字符串:
'There was a cat in the house yesterday'
'Did you see a cat in the house today'
我希望将字符串分解为捕获组,以便匹配对象 m.groups()
将分别 return 每个字符串的以下内容:
('There', ' was a cat in the house ', 'yesterday')
('Did', ' you see a cat in the house ', 'today')
最初,我想出了以下正则表达式:
r = re.compile('^(There|Did) ( |[A-Za-z])+ (today|yesterday)$')
但是这个 returns:
('There', 'e', 'yesterday')
('Did', 'e', 'today')
所以它只给我在中间组中匹配的最后一个字符。我了解到这不起作用,因为捕获组只会 return 最后一次匹配的迭代。所以我在中间捕获组周围加上括号,如下所示:
r = re.compile('^(There|Did) (( |[A-Za-z])+) (today|yesterday)$')
但是现在,虽然它至少捕获了中间组,但它也在 m.groups()
中 return 增加了一个额外的 "e" 字符,即:
('There', 'was a cat in the house', 'e', 'yesterday')
...虽然我觉得这与回溯有关,但我无法弄清楚为什么会这样。有人可以向我解释为什么我会得到这个结果,以及我如何才能得到想要的结果吗?
您可以简化当前的正则表达式,并获得正确的行为,方法是将中间的捕获组替换为匹配任何字符的 .
(点)运算符,然后是 *
( asterisk) 运算符重复匹配任何字符:
import re
s1 = 'There was a cat in the house yesterday'
s2 = 'Did you see a cat in the house today'
x = re.compile("(There|Did)(.*)(today|yesterday)")
g1 = x.search(s1).groups()
g2 = x.search(s2).groups()
print(g1)
print(g2)
产生这个输出:
('There', ' was a cat in the house ', 'yesterday')
('Did', ' you see a cat in the house ', 'today')
A repeated capturing group will only capture the last iteration. Put a
capturing group around the repeated group to capture all iterations or
use a non-capturing group instead if you're not interested in the
data.
这是按预期重新工作的结果:
^(There|Did) ([ A-Za-z]+) (today|yesterday)$
r = re.compile('^(There|Did) (( |[A-Za-z])+) (today|yesterday)$')
^ ^ ^
你有一些不必要的东西。把那些去掉,并在你的中间组中包含空格:
r = re.compile('^(There|Did) ([A-Za-z ]+) (today|yesterday)$')
^ space
示例:
>>> r = re.compile('^(There|Did) ([A-Za-z ]+) (today|yesterday)$')
>>> r.search('There was a a cat in the hosue yesterday').groups()
('There', 'was a a cat in the hosue', 'yesterday')
此外,如果您希望空格成为中间(第二)组的一部分,请去掉捕获组之间的空格
我正在尝试创建一个正则表达式,它将接受字符串并将它们分成三组:(1) 字符串开头的特定单词列表中的任何一个。 (2) 字符串末尾的特定单词列表中的任何一个。 (3) 这两场比赛之间的所有 letters/whitespace。
作为示例,我将使用以下两个字符串:
'There was a cat in the house yesterday'
'Did you see a cat in the house today'
我希望将字符串分解为捕获组,以便匹配对象 m.groups()
将分别 return 每个字符串的以下内容:
('There', ' was a cat in the house ', 'yesterday')
('Did', ' you see a cat in the house ', 'today')
最初,我想出了以下正则表达式:
r = re.compile('^(There|Did) ( |[A-Za-z])+ (today|yesterday)$')
但是这个 returns:
('There', 'e', 'yesterday')
('Did', 'e', 'today')
所以它只给我在中间组中匹配的最后一个字符。我了解到这不起作用,因为捕获组只会 return 最后一次匹配的迭代。所以我在中间捕获组周围加上括号,如下所示:
r = re.compile('^(There|Did) (( |[A-Za-z])+) (today|yesterday)$')
但是现在,虽然它至少捕获了中间组,但它也在 m.groups()
中 return 增加了一个额外的 "e" 字符,即:
('There', 'was a cat in the house', 'e', 'yesterday')
...虽然我觉得这与回溯有关,但我无法弄清楚为什么会这样。有人可以向我解释为什么我会得到这个结果,以及我如何才能得到想要的结果吗?
您可以简化当前的正则表达式,并获得正确的行为,方法是将中间的捕获组替换为匹配任何字符的 .
(点)运算符,然后是 *
( asterisk) 运算符重复匹配任何字符:
import re
s1 = 'There was a cat in the house yesterday'
s2 = 'Did you see a cat in the house today'
x = re.compile("(There|Did)(.*)(today|yesterday)")
g1 = x.search(s1).groups()
g2 = x.search(s2).groups()
print(g1)
print(g2)
产生这个输出:
('There', ' was a cat in the house ', 'yesterday')
('Did', ' you see a cat in the house ', 'today')
A repeated capturing group will only capture the last iteration. Put a capturing group around the repeated group to capture all iterations or use a non-capturing group instead if you're not interested in the data.
这是按预期重新工作的结果:
^(There|Did) ([ A-Za-z]+) (today|yesterday)$
r = re.compile('^(There|Did) (( |[A-Za-z])+) (today|yesterday)$')
^ ^ ^
你有一些不必要的东西。把那些去掉,并在你的中间组中包含空格:
r = re.compile('^(There|Did) ([A-Za-z ]+) (today|yesterday)$')
^ space
示例:
>>> r = re.compile('^(There|Did) ([A-Za-z ]+) (today|yesterday)$')
>>> r.search('There was a a cat in the hosue yesterday').groups()
('There', 'was a a cat in the hosue', 'yesterday')
此外,如果您希望空格成为中间(第二)组的一部分,请去掉捕获组之间的空格