擅长:python、mysql、java
<p>通过将regex的每个元素都包装在捕获括号中,可以更好地理解发生了什么:</p>
<pre><code>import re
rgx1 = re.compile(r'(a)(.*?)(b)?(.*?)(c)?(d)')
m1 = rgx1.search('axxxxxbcd')
print(m1.groups())
</code></pre>
<p>输出:</p>
<pre><code>('a', '', None, 'xxxxxb', 'c', 'd')
</code></pre>
<p>下面是发生的情况:</p>
<pre><code># 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'
</code></pre>
<p>为什么第4组的结果是内容而不是第2组?最初,它们是相同的,捕获尽可能少(没有),但这将导致整个regex失败。所以发动机必须开始膨胀第2组或第4组。基于这一个例子,似乎引擎首先扩展了后一个组,但我不知道在这种情况下具体的实现规则是什么。为了证明这两个组确实采用了非贪婪策略,可以在字符串的前面添加<code>d</code>:例如,使用输入文本<code>axxdxxxbcd</code>。在这种情况下,第4组只持有<code>xx</code>。你知道吗</p>
<p>以下方法可以满足您的需要:</p>
<pre><code>rgx1 = re.compile(r'(a)(?:.*?(b)|.*?)(?:.*?(c)|.*?)(d)')
m1 = rgx1.search('a...b...cd')
print(m1.groups()) # Output: ('a', 'b', 'c', 'd')
</code></pre>
<p>但我可能不会那样解决问题。正则表达式中的每个(或几乎每个)元素都是可选的,通常很难正确处理。有时,最好在几个简单的阶段中解析文本,而不是在一个大而复杂的正则表达式中。你知道吗</p>