这个问题是关于'''的操作。在我之前的问题中,有人错误地将我的问题标记为重复。所以我重新打开这个问题,寻求答案。
我想问为什么第一个表达式不会从字符串'axxxxxbcd'输出('a','b','c','d')。
import re
match = re.findall(r'(a).*?(b)?.*?(c)?(d)','awsssd axxxxxbcd ad adfdfdcdfdd
awsbdfdfdcd')
print (match)
输出[1]:[('a','','','d'),('a','','c','d'),('a','', '','d'),('a','','','d'),('a','','','d')]
import re
match = re.findall(r'(a).*?(b)?(c)?(d)','awsssd axxxxxbcd ad adfdfdcdfdd awsbdfdfdcd')
print (match)
输出[2]:[('a','','','d'),('a','b','c','d'),('a','' ,'','d'),('a','','','d'),('a','b','','d')]
@Isaac
答案 0 :(得分:1)
通过在捕获括号中包装正则表达式的每个元素,您可以更好地了解正在发生的事情:
import re
rgx1 = re.compile(r'(a)(.*?)(b)?(.*?)(c)?(d)')
m1 = rgx1.search('axxxxxbcd')
print(m1.groups())
输出:
('a', '', None, 'xxxxxb', 'c', 'd')
以下是发生的事情:
# Group 1: 'a'
# Group 2: capture as little as possible, so we get ''
# Group 3: 'b' is not present, but it's optional, so we get None
# Group 4: 'xxxxxb'
# Group 5: 'c'
# Group 6: 'd'
为什么第4组最终会使用内容而不是第2组?最初,它们是相同的,捕获尽可能少(没有),但这将导致整体正则表达式失败。所以引擎必须开始扩展第2组或第4组。基于这个例子,看起来引擎首先扩展了后者 - 但我不知道对于这样的情况,精确的实现规则是什么。为了证明这两个组确实采用非贪婪策略,您可以在字符串中添加d
:例如,使用输入文本axxdxxxbcd
。在这种情况下,第4组最终仅持有xx
。
以下方法可能会达到您想要的效果:
rgx1 = re.compile(r'(a)(?:.*?(b)|.*?)(?:.*?(c)|.*?)(d)')
m1 = rgx1.search('a...b...cd')
print(m1.groups()) # Output: ('a', 'b', 'c', 'd')
但我可能不会那样解决问题。每个(或几乎每个)元素都是可选的正则表达式通常很难实现。有时候你最好在几个简单的阶段解析文本而不是大毛茸茸的正则表达式。
答案 1 :(得分:0)
你得到的输出是因为 。*?匹配任何字符(行终止符除外
(a).*?(b)?.*?(c)?(d)
Group 1. 0-1 `a`
Group 3. 7-8 `c`
Group 4. 8-9 `d`
第一捕获小组(a)
a字面匹配字符(区分大小写) 。*?匹配任何字符(行终止符除外) *?量词 - 在零和无限时间之间匹配,尽可能少,根据需要扩展(懒惰)
第二捕获组(b)?
?量词 - 匹配0到1次,尽可能多次,根据需要回馈(贪婪) b字面匹配字符b(区分大小写) 。*?匹配任何字符(行终止符除外) *?量词 - 在零和无限时间之间匹配,尽可能少,根据需要扩展(懒惰)
第三捕获组(c)?
?量词 - 匹配0到1次,尽可能多次,根据需要回馈(贪婪) c字面匹配字符c(区分大小写)
第四捕获组(d) d字面匹配字符d(区分大小写)
但是,如果你想从字符串&#输出(' a'' b',' c'' d') 39; axxxxxbcd'
你的正则表达式应该是
(a).*?(b)?(c)?(d)
Group 1. 0-1 `a`
Group 2. 6-7 `b`
Group 3. 7-8 `c`
Group 4. 8-9 `d`