这是我从文档中得到的:\zs与前面的正则表达式匹配后“启动突出显示的部分”,而\@<=与前面的原子匹配后“启动突出显示的部分”。但是我并不完全理解它的微妙之处,所以谁能解释它们在深度上有何不同?

这就是让我感到好奇的原因:如果我跑步

/\_s\zsnnoremap


ie选择nnoremap前面有一个空格或行的开头(即换行,因此是前一行的换行,因此是\_之前的s),然后运行gn进入可视模式并直观地选择下一个匹配项,由于某种原因,仅第一个匹配项列(即n中的第一个nnoremap)被选中-尽管整个nnoremap单词都在打开:hlsearch的情况下突出显示。

但是,如果我改为运行搜索
/>
/\_s\@<=nnoremap


,然后尝试gn,正确选择了整个nnoremap。这可能是怎么回事?我(敢说)发现了一些晦涩的错误吗?

评论

我认为它是:h模式,但我的记忆表明正则表达式由原子组成,如果这有助于解释差异。

#1 楼

看起来您确实发现了一个晦涩的错误。我早在2012年就为Vim 7.3实现了gn文本对象。它基本上按以下方式工作:

1)向后搜索当前正则表达式的最后一个匹配项。

2)向前搜索该正则表达式的下一个匹配项。当前正则表达式。

这应该使光标清楚,即使在1)的开头已经位于下一个匹配项的开头。最后

3)它搜索当前正则表达式的结尾。并将光标放在此处。

现在发生的是,对当前比赛结束处的搜索回绕并移回到上一个比赛结束处(因为在已禁用1))。然后将Visual标记设置为从起点(点2的终点)到下一个搜索项3所移动到的区域。

我将仔细研究这个问题,并将可能稍后再提交Vim补丁。

[更新22.05.2018]我已经编写并提交了补丁来修复此问题。

[Update2 22.05.2018]
该补丁已合并为补丁级别8.1.0018

[更新22.10.2019]
自Vim补丁8.1.629起,不再执行第三步。现在,Vim现在可以在找到比赛开始时确定比赛结束(第2步)

#2 楼

Christian已经完全解决了gn的越野车问题,但\zs\@<=之间仍然存在根本差异。正则表达式中最大的一个\@<=修饰前一个原子,而\zs是iself中的原子。

考虑:匹配列1,那里有一个X。 \%1c只是使匹配在X后面的位置重新开始。正则表达式2不匹配,因为尽管\zs与第一列匹配,但\%1c的宽度为零(如文档中所述),并且X\@<=从第2列开始。补齐第1列和第2列之间的位置差。

正则表达式3匹配,因为nnoremap从第2列开始。

评论


我不认为正则表达式2会失败,因为没有什么可以弥补第1列和第2列之间的位置差异。如果是这个问题,那么从正则表达式中删除nnoremap会产生匹配;但是即使没有,正则表达式仍然会失败。我认为它失败了,因为\%1cX \ @ <=表示了一个不存在的位置。 \%1c匹配第1列的位置,X \ @ <=要求在此之前匹配字符X。但是第一列之前不能有任何字符。这就是为什么即使用点(任何字符)替换X,正则表达式\%1c。\ @ <=仍然会失败。

–user938271
19-09-4在18:12



#3 楼

\zs适用于整个正则表达式,并将下一个字符设置为整个匹配的第一个字符。 \zs之前的任何内容都不会包含在匹配文本中。另一方面,\@<=仅影响直接在其周围的原子,允许您指定下一个原子仅在以下情况下才匹配它跟随前面的原子。因此,例如,正则表达式:

\vbar.*(foo)@<=bar


将匹配bar的两个实例(包括实例本身)之间的所有文本,但前提是第二个前面带有foo。也就是说,它将匹配:

barbazfoobar


,但不匹配:

barbazbazbar


,因为\@<=以此方式进行了本地化,甚至可以在单个表达式中多次使用\@<=

\vbar.*(foo)@<=bar.*(foo)@<=bar


以下内容将匹配bar的三个实例,但前提是后两个实例均以foo开头。

ie给定文本:

barfoobarbazfoobar
barfoobarbazbazbar
barbazbarbazfoobar


仅与第一行匹配。

评论


但是您可以用\ zs交换后面的第一个后视,也就是说,这也应该起作用:\ vfoo \ zsbar。*(foo)@ <= bar。

– Karl YngveLervåg
18年5月22日在6:48



@KarlYngveLervåg好点。我进行了编辑,以使区别更加清晰,并使用其中无法完全替换\ zs的示例。

–丰富
18年5月22日在8:46

因此,据我了解,\ zs和\ ze可以替换为正则表达式模式,它们更强大,对吗?更强大的功能是,它们可以多次使用,并且可以与\(\)分组。也因为它们像Perl的正则表达式一样工作。有什么事吗

–klaus
19 Mar 20 '19在10:36

@klaus这听起来对我来说是正确的(尽管我不是专家)。请注意,您应该尽可能使用\ zs / \ ze,因为它们比环顾四周快。

–丰富
19年3月29日在9:04

明白了\ zs和\ ze显然更直观。感谢您的解释。

–klaus
19年3月29日在9:24