在vim中查找精确匹配

23
使用/或者?能够在vim中找到一个单词的匹配。但是如果我想要查找一个完全匹配怎么办呢?比如说,我的文本包含以下单词:a aa aaa aaaa aa,并且我输入了/aa。这会找到所有包含模式aa的字符串,但是如果我想要找到完全匹配的aa而不是aaaa aaaa呢?
5个回答

47

你需要用 \<\> 包含你要查找的字符串,就像这样 /\<aa\> 来精确匹配该字符串。


2
只有在存在关键字边界时才有效;例如,在 xaax 中查找匹配项将失败。 - Ingo Karkat
哇,我不知道那个!对于你的例子,键“*”和“#”也不起作用。 - LSchueler

10

为了找到一个单独的、独立的aa(不是aaaa,...),你需要断言该字符之前和之后都没有匹配。这可以通过负向向后查找(在Vim的正则表达式语法中为\@<!)和向前查找\@!)包含匹配本身(a\{2})来实现:

/\%(a\)\@<!a\{2}\%(a\)\@!/

简化

如果匹配边界也是一个非关键字/关键字边界,那么这些断言很难输入,您可以使用更短的 \<\a\{2}\> 断言(如LSchueler的答案中所示),但这在一般情况下不起作用,例如对于xaax


2
我会使用aa代替a\{2}。由于a已经是一个(字面上的)原子,我会省略分组字符:/a\@<!aaa\@<!/。看着那个具有欺骗性的aaa,我可能会决定a\{2}更清晰明了。 - benjifisher

2
你可以搜索aa[^a],这将找到你需要的两个 a,没有别的内容。
编辑:哦,伙计们,你们想要一个精确匹配:-) 所以,为了完全匹配两个aa且不匹配其他任何字符:
[^a]\zsaa\ze[^a]\|^\zsaa\ze$\|^\zsaa\ze[^a]\|[^a]\zsaa\ze$

然后这些分支扩展了出去:

  [^a]\zsaa\ze[^a]
\|^\zsaa\ze$
\|^\zsaa\ze[^a]
\|[^a]\zsaa\ze$

这些覆盖了所有情况--aa可以位于任何行的开头、中间或结尾。而且不能有超过两个连在一起的a

  • \zs表示实际匹配从这里开始
  • \ze表示实际匹配在这里结束
  • 第一分支在一行包含其他字符的情况下找到aa
  • 第二分支在整个行中找到aa
  • 第三分支在一行开头找到aa
  • 第四分支在一行结尾找到aa

我对像“look-behind assertions”这样的花哨东西感到困惑,所以我试图坚持相当简单的正则表达式概念。

编辑2:请查看@benjifisher更简化、更优雅版本下面,供您欣赏。


这也将匹配aaaaaaa末尾的aa,因此我给@MosteM的答案加上+1。 - benjifisher
而且当后面没有字符时,它将无法工作,例如在行末。 - Ingo Karkat
1
这真的很有趣!首先,^\zs\ze$的构造比必要的更复杂:使用^$可以得到相同的结果。其次,我认为使用 \(^\|[^a]\)\zsaa\ze\([^a]\|$\) 可以节省一些字符。在这种情况下,你可以自己决定缩短是否更易读。 - benjifisher
@benjifisher - 我向你的卓越智慧致敬。你的缩短版本确实像广告中所说的那样有效。我将保留我的最后一个 regex,因为它也完成了任务,并且是思考这个问题的好起点。但是我会在注释中指向你的建议。 - Yawar

2

这个简单的方法帮助我精确匹配了模式。你可以试试这个。

\V\c\<pattern_here\>

0
将光标移动到您想要搜索的确切单词上。
按 * 键(可以是 Shitf+8 或键盘数字键区)进行搜索。

2
这非常方便,但矛盾的是它依赖于首先找到至少一个您要查找的字符串实例。不过,对于快速定位重复项来说非常棒! - Timmah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接