<p><strong>问题是<em>匹配两个字符串之间的最短窗口</em>@flodel正确地提到正则表达式引擎从左到右解析字符串,因此所有匹配项都是<em>最左边的</em>。贪婪和懒惰只适用于右边的边界:贪婪的量词将子字符串添加到最右边的边界,而懒惰的量词将匹配到后面第一个出现的子模式</p>
<p>请参见示例</strong>:</p>
<pre><code>> library(stringr)
> str_extract('xxx aaaab yyy', "a[^ab]*b")
[1] "ab"
> str_extract('xxx aaa xxx aaa zzz', "xxx.*?zzz")
[1] "xxx aaa xxx aaa zzz"
> str_extract('xxx aaa xxx aaa zzz', "xxx(?:(?!xxx|zzz).)*zzz")
[1] "xxx aaa zzz"
</code></pre>
<p>第一个和第三个场景返回最短的窗口,第二个场景是当前问题的说明,但具有多字符输入</p>
<p><strong>情景1。边界是单个字符</strong></p>
<p>如果<code>a</code>和<code>b</code>是单个字符,则通过使用求反字符类找到最短的窗口<code>a[^ab]*b</code>将很容易地从<code>a</code>到下一个<code>b</code>抓取子字符串,中间没有<code>a</code>和<code>b</code></p>
<p><strong>场景2。边界不是单个字符</strong></p>
<p>在这些情况下,您可以使用<a href="https://stackoverflow.com/a/37343088/3832970"><em>tempered greedy token</em></a>来进一步展开。<code>xxx(?:(?!xxx|zzz).)*zzz</code>模式匹配<code>xxx</code>,然后任何0+字符(不是<code>xxx</code>或<code>zzz</code>字符序列的起始字符的换行符字符除外)匹配<code>(?!xxx|zzz)</code>是一个<em>负前瞻</em>,如果右边的子字符串与前瞻模式匹配,则匹配失败),然后是一个<code>zzz</code></p>
<p>这些<em>匹配</em>场景可以很容易地与基本R<code>regmatches</code>(使用支持lookaheads的PCRE regex风格)一起使用:</p>
<pre><code>> x <- 'xxx aaa xxx aaa zzz xxx bbb xxx ccc zzz'
> unlist(regmatches(x, gregexpr("xxx(?:(?!xxx|zzz).)*zzz", x, perl = TRUE)))
[1] "xxx aaa zzz" "xxx ccc zzz"
</code></pre>
<p>注意:当在base R中使用PCRE正则表达式或在<code>str_extract</code>/<code>str_match</code>中使用ICU正则表达式时,<code>.</code>与换行符不匹配,要启用该行为,需要在模式开始处添加<code>(?s)</code>(内联DOTALL修饰符)</p>