Vim正则表达式匹配带有前缀和后缀的字符串

43

我想在vim中查找以"abc"开头,以"xyz"结尾的字符串。

以下是我尝试过的命令:

:1,$g/abc[\w\W]*xyz/
:1,$g/abc\[\\w\\W\]\*xyz/
:1,$g/abc*xyz/

"[\w\W]*"意味着在“abc”和“xyz”之间的文本可以是任何字符。

"1,$"表示vim打开的文件中搜索范围是从第一行到最后一行。

我发现搜索模式

abc[\w\W]*xyz 

https://regex101.com/ 运作正常,但为什么在 vim 中失败?


4
使用点号代替 [\w\W]。 - Avinash Raj
3
Vim的正则表达式与由regex101使用的PCRE有一些差异。如需更多细节,请参阅此问题。但我不确定[\w\W]是否是它们之间的差异之一。 - SSC
4
Vim支持在集合内使用某些字符类,但仅限于有限的子集(例如[[:alpha:]]有效,但[\w]无效)。您可以查看:help /[]以了解支持的字符类。 - Marth
1
你可能想在你的 .vimrc 文件中添加 set incsearch。这将允许你构建正则表达式并在输入时查看匹配项(使用 / 而不是 :global)。这有助于我构建更复杂的正则表达式,因为你可以立即知道错误的位置,而不必输入整个表达式然后猜测。 - W. B. Reed
4个回答

53
下面的命令应该能够正常工作,除非 "任何字符" 对于您和 Vim 的含义不同:
:g/abc.*xyz
  • . 表示“除换行符外的任何字符”。
  • * 表示“前面的原子可以出现任意次数(包括 0 次)”。
  • 1,$ 可以缩写为 %
  • :global 默认作用于整个缓冲区,因此甚至不需要使用 %
  • 如果在 :g/pattern 后没有跟随命令,如 :g/foo/d,则不需要使用闭合的 /

为什么我们在这里使用:global?只是出于好奇。只使用搜索/abc.*xyz就可以了。此外,如果用户设置了incsearch,他们可以使用/在键入时看到他们的搜索结果,但不能使用:global。澄清一下,使用:global没有任何问题,只是对我来说有点奇怪。 - W. B. Reed
1
@W.B. Reed,我使用:global是因为这是OP给出的例子。请注意,:global/的目的大不相同:/:global完全不能互换。 - romainl
1
好的,我同意。只是似乎OP想要搜索一个字符串。因此,/更合适。如果他们只想搜索一个字符串,那么/regex:g/regex更合适。当您想要对这些匹配项执行某些操作时,使用:g更为合适。 - W. B. Reed

8
当文件变得太大时(比如1GB),“:g/abc.*xyz”命令变得非常缓慢。
我发现:
cat fileName | grep abc | grep xyz >> searchResult.txt

这种方法比在vim中使用搜索功能更为高效。

我知道这种方法可能会返回以“xyz”开头并以“abc”结尾的行。

但由于在我的文件中这是很少见的情况(也许其他人也不经常遇到),所以我认为应该在这里写下这种方法。


1
我也使用这种方法,通常用于长日志文件。然后,您可以将任何两个grep的输出(之一)传输到sed中,以仅选择“abc.*xyz”情况。 - P2000

1

看起来在集合语法[..]内部,例如\w不能使用等字符类,可能是因为它通过逐个字符的策略进行测试。来自:h/[]

与集合匹配可能很慢,因为文本中的每个字符都必须与集合中的每个字符进行比较。尽可能使用上面的其他原子。例如:“\d”比“[0-9]”快得多,并且匹配相同的字符。

但是,您可以使用专门为[..]语法准备的类似功能。再次来自:h/[]

字符类表达式被评估为属于该字符类的字符集。

示例包括:

[:alnum:]     letters and digits                   
[:alpha:]     letters                              
[:blank:]     space and tab characters             
[:cntrl:]     control characters                   
[:digit:]     decimal digits                       
[:graph:]     printable characters excluding space 
[:lower:]     lowercase letters

0

如果你想逐个查找它们,可以点击

/

然后写入

abc.*xyz

按下回车键查找模式的第一个出现。然后使用n查找下一个出现,使用Shift + n查找上一个出现。这是我通常的做法,因为对我来说更容易修改这些行。


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