Vimscript:获取字符串中正则表达式的所有匹配项

5
在vimscript中,我们有substitute函数,它将接受标志'g'以替换所有出现的内容。
是否有一种方法可以获得所有匹配字符串?
例如,使用字符串'x y z',我们可以使用substitute('x y z', '[a-z]', 'abc', 'g')将其更改为abc abc abc
但是,是否有任何方法可以获取单个字符['x','y','z']
我知道我们可以使用match()来获取匹配位置,并使用matchstr()来获取匹配的字符串。 但是如果我想遍历所有匹配项,则必须调用这两个函数,我认为这不是有效的方法。
因此,在vimscript中获取字符串的所有匹配项是否有有效的方法?

你可以捕获匹配的字符串,然后使用反向引用访问它。类似这样:substitute('x y z', '([a-z])', '\1', 'g') 将会得到 x y z - Anurag Peshne
@AnuragPeshne 这样,我将拥有额外的东西(空格),这些东西与模式不匹配。比如说,我想从“ax bx cy”中提取“'a', 'b', 'c'”。而且,使用“substitute('ax bx cy', '([a-c])', '\1', 'g')”仍然会给我未匹配的字符('x'、'y'和空格)。 - LotAbout
这是因为您的替换表达式与捕获表达式相同。执行 substitute('ax bx cy', '\([a-c]\)[x-y]', '\1', 'g') 将消耗 'x' 和 'y' 并返回 'a b c'。 - Anurag Peshne
substitute('ax bx cy', '\([a-c]\)[x-y] \?', '\1', 'g') 将会消耗空格。 - Anurag Peshne
@AnuragPeshne 我明白。这意味着我必须编写我关心的模式以及我不关心(在这种情况下是空格)的内容的模式来剥离它。而且我认为这不够方便。 - LotAbout
我同意,不过我有另一个想法:substitute('ax bx cy', '\([a-c]\)[^a-c]', '\1', 'g') - 即捕获所关心的模式,然后否定相同的模式。 - Anurag Peshne
2个回答

18

您可以使用一个带有子替换表达式的替代方案来捕获所有匹配项。

let str = 'a b c'
let lst = []
call substitute(str, '[a-z]', '\=add(lst, submatch(0))', 'g')

更多帮助请参见:

:h sub-replace-expression
:h substitute
:h add()
:h submatch()

2

如果您可以否定正则表达式以匹配不需要的内容,您可以使用split()函数;它将从字符串中删除所有匹配项,并返回其余部分的列表:

:echo split('x y z', ' ')
['x', 'y', 'z']

1
使用 '\v\ze(x|y|z)',所有匹配的元素都是解决方案 -> :echo map(filter(split(the_string, '\v\ze'.pat), 'v:val =~ "\\v^".pat'), 'matchstr(v:val, "\\v^".pat)') - Luc Hermitte
@LucHermitte 这个\ze技巧真的很神奇!不过我认为Peter的解决方案更直观。 - LotAbout
每当我需要使用split()函数来解决问题时,我都要花费很多时间去寻找“上次我是怎么做的?”大多数情况下,我会发现还有更简单的方法。 - Luc Hermitte

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