<p>这对pythonregex来说是一个很好的问题,因为在我看来,<code>re</code>模块是{a1}。这就是为什么对于Python中任何严肃的regex工作,我都会求助于matthewbarnett的stellar<a href="https://pypi.python.org/pypi/regex" rel="nofollow">regex</a>模块,它集成了Perl、PCRE和.NET的一些优秀特性。在</p>
<p>我将向您展示的解决方案可以适应使用<code>re</code>,但是使用<code>regex</code>更具可读性,因为它是模块化的。另外,将它作为更复杂的嵌套匹配的起始块,因为<code>regex</code>允许您编写与Perl和PCRE中类似的<a href="http://www.rexegg.com/regex-recursion.html" rel="nofollow">recursive regular expressions</a>。在</p>
<p>好了,说够了,这里是代码(除了导入和定义只有四行)。请不要让长正则表达式吓到你:它很长,因为它是为可读而设计的。解释如下。在</p>
<p><strong>代码</strong></p>
<pre><code>import regex
quote = regex.compile(r'''(?x)
(?(DEFINE)
(?<qmark>["']) # what we'll consider a quotation mark
(?<not_qmark>[^'"]+) # chunk without quotes
(?<a_quote>(?P<qopen>(?&qmark))(?&not_qmark)(?P=qopen)) # a non-nested quote
) # End DEFINE block
# Start Match block
(?&a_quote)
|
(?P<open>(?&qmark))
(?&not_qmark)?
(?P<quote>(?&a_quote))
(?&not_qmark)?
(?P=open)
''')
str = """'Well, I have tried to say "How Doth the Little Busy Bee," but it all came different!' Alice replied in a very melancholy voice. She continued, 'I will try again.'"""
for match in quote.finditer(str):
print(match.group())
if match.group('quote'):
print(match.group('quote'))
</code></pre>
<p><strong>输出</strong></p>
^{pr2}$
<p><strong>工作原理</strong></p>
<p>首先,为了简化,请注意,我已经自由地将<code>I'll</code>转换为<code>I will</code>,减少了引号的混淆。对<code>I'll</code>进行寻址对于否定的lookahead是没有问题的,但是我想让regex可读。在</p>
<p>在<code>(?(DEFINE)...)</code>块中,我们定义了三个子表达式<code>qmark</code>、<code>not_qmark</code>和{<cd11>},这与定义变量或子例程以避免重复一样。在</p>
<p>在定义块之后,我们继续匹配:</p>
<ul>
<li><code>(?&a_quote)</code>匹配整个引号</li>
<li><code>|</code>或者。。。在</li>
<li>^{14{14}匹配<cd15}</li>
<li><code>(?&not_qmark)?</code>匹配非引号的可选文本</li>
<li><code>(?P<quote>(?&a_quote))</code>匹配一个完整的引号并将其捕获到<code>quote</code>组中</li>
<li><code>(?&not_qmark)?</code>匹配非引号的可选文本</li>
<li><code>(?P=open)</code>与在引号开头捕获的引号匹配。在</li>
</ul>
<p>Python代码只需要打印匹配项和<code>quote</code>捕获组(如果存在的话)。在</p>
<p>这个可以精炼吗?当然。以这种方式使用<code>(?(DEFINE)...)</code>,可以构建漂亮的模式,以后可以重新阅读和理解。在</p>
<p><strong>添加递归</strong></p>
<p>如果您想使用纯正则表达式处理更复杂的嵌套,则需要使用递归。在</p>
<p>要添加递归,只需定义一个组并使用子例程语法引用它。{23>在组内执行代码。要在组<code>something</code>中执行代码,请使用<code>(?&something)</code>。记住,通过使递归成为可选的(<code>?</code>)或交替的一侧,为引擎留下一个出口。在</p>
<p><strong>参考文献</strong></p>
<ul>
<li><a href="http://www.rexegg.com/regex-disambiguation.html#define" rel="nofollow">Pre-defined regex subroutines</a></li>
<li><a href="http://www.rexegg.com/regex-capture.html#namedgroups" rel="nofollow">Named capture groups</a></li>
</ul>