在Vim中,如何在子表达式中进行替换?
In Vim, How to substitute within a subexpression?
我想在我所有的 class 名称前加上 o-
,而不必手动调整每个 class 名称。我用 Vim.
我知道替代品可以完成这项工作,所以我想到了这个,这显然不起作用(也是我在这里的原因)。
:%s/class="[^"]*"/\='class="'.substitute(submatch(0), '[^o-]*', 'o-'.submatch(1), 'g').'"'/g
解释:
class="[^"]
- 匹配 class="foo bar baz"
的所有实例
\='class="'.substitute(subexp).'"'
- 替换找到的实例 class="subexp"
subexp
中的每个 space 应该用原来的 class 前缀替换 class class o-
总而言之,在程序方面,对于每个 class="foo bar baz"
,将每个 class 名称替换为带有 o-
前缀的 class 名称。
提前致谢。
(奖金)编辑:如何编写以忽略或处理 class 已经以 o-
开头的名称,当遇到时,所以o-o-
是 而不是 编辑结果。
一种方法是利用 \zs...\ze
,并且 submatch(0)
解析为 \zs...\ze
:
之间匹配的字符串
:%s/\mclass="\zs.\{-}\ze"/\=substitute(submatch(0), '\<', 'o-', 'g')/g
如果您不想依赖它,您仍然可以使用显式分组:
:%s/\mclass="\zs\([^"]*\)\ze"/\=substitute(submatch(1), '\<', 'o-', 'g')/g
举个例子
class="foo bar baz"
这一行有效:
%s/class="\zs[^"]*\ze"/\=join( map(split(submatch(0)),"'o-'.v:val"), ' ')/
所以有嵌套的函数调用:
- 我没有使用
\<
边界,因为如果你的 class 名称中有一些 "special" 字符,它将失败。例如。 # - or @
。不知道你们的语言是不是这样。
- submatch(0) 是
"foo bar baz"
split()
使其(每个 class)进入列表
map()
将 o-
添加到每个 classname
join()
将修改后的列表转回字符串
所以执行这条命令后,你应该看到:
class="o-foo o-bar o-baz"
编辑 "Bonus" 要求:
我们只需要检查每个元素(class名称)。检查下面的代码,它应该适合你:
%s/class="\zs[^"]*/\=join(map(split(submatch(0)),"(v:val=~'^o-'?'':'o-').v:val"))/
这里我们有:
(v:val=~'^o-'?'':'o-').v:val
如果元素以 o-
开头,那么我们不再添加另一个 o-
。
我想在我所有的 class 名称前加上 o-
,而不必手动调整每个 class 名称。我用 Vim.
我知道替代品可以完成这项工作,所以我想到了这个,这显然不起作用(也是我在这里的原因)。
:%s/class="[^"]*"/\='class="'.substitute(submatch(0), '[^o-]*', 'o-'.submatch(1), 'g').'"'/g
解释:
class="[^"]
- 匹配class="foo bar baz"
的所有实例
\='class="'.substitute(subexp).'"'
- 替换找到的实例class="subexp"
subexp
中的每个 space 应该用原来的 class 前缀替换 class classo-
总而言之,在程序方面,对于每个 class="foo bar baz"
,将每个 class 名称替换为带有 o-
前缀的 class 名称。
提前致谢。
(奖金)编辑:如何编写以忽略或处理 class 已经以 o-
开头的名称,当遇到时,所以o-o-
是 而不是 编辑结果。
一种方法是利用 \zs...\ze
,并且 submatch(0)
解析为 \zs...\ze
:
:%s/\mclass="\zs.\{-}\ze"/\=substitute(submatch(0), '\<', 'o-', 'g')/g
如果您不想依赖它,您仍然可以使用显式分组:
:%s/\mclass="\zs\([^"]*\)\ze"/\=substitute(submatch(1), '\<', 'o-', 'g')/g
举个例子
class="foo bar baz"
这一行有效:
%s/class="\zs[^"]*\ze"/\=join( map(split(submatch(0)),"'o-'.v:val"), ' ')/
所以有嵌套的函数调用:
- 我没有使用
\<
边界,因为如果你的 class 名称中有一些 "special" 字符,它将失败。例如。# - or @
。不知道你们的语言是不是这样。 - submatch(0) 是
"foo bar baz"
split()
使其(每个 class)进入列表map()
将o-
添加到每个 classnamejoin()
将修改后的列表转回字符串
所以执行这条命令后,你应该看到:
class="o-foo o-bar o-baz"
编辑 "Bonus" 要求:
我们只需要检查每个元素(class名称)。检查下面的代码,它应该适合你:
%s/class="\zs[^"]*/\=join(map(split(submatch(0)),"(v:val=~'^o-'?'':'o-').v:val"))/
这里我们有:
(v:val=~'^o-'?'':'o-').v:val
如果元素以 o-
开头,那么我们不再添加另一个 o-
。