In Vim, How to substitute within a subexpression?

时间:2015-12-10 01:36:49

标签: regex vim substitution

I want to prepend all my classNames with o- without having to adjust every className by hand. I use Vim.

I know a substitution will do the job so I came up with this, which is obviously not working (and the reason I am here).

:%s/class="[^"]*"/\='class="'.substitute(submatch(0), '[^o-]*', 'o-'.submatch(1), 'g').'"'/g

Explanation:

  1. class="[^"] - matches all instances of class="foo bar baz"
  2. \='class="'.substitute(subexp).'"' - replaces the found instances class="subexp"
  3. subexp in two should repace each space separated class with the original className prepended with o-

All in all, in procedural terms, for each class="foo bar baz", replace each className with the className prepended with o-.

Thanks in advance.

(BONUS) EDIT: How can this be written to ignore or cope with classNames that already begin with o-, when encountered, so that o-o- is not a resulting edit.

2 个答案:

答案 0 :(得分:4)

示例

class="foo bar baz"

此行有效:

%s/class="\zs[^"]*\ze"/\=join( map(split(submatch(0)),"'o-'.v:val"), ' ')/

所以有嵌套函数调用:

  • 我没有使用\<边界,因为如果你的类名中有一些“特殊”字符,它就会失败。例如。 # - or @。我不知道你的语言是否属实。
  • submatch(0)是"foo bar baz"
  • split()使(每个类)成为列表
  • map()为每个类名
  • 添加o-
  • join()将修改后的列表转回字符串

执行此命令后,您应该看到:

class="o-foo o-bar o-baz"

编辑“奖金”要求:

我们只需要检查每个元素(classname)。检查下面的代码,它应该适合你:

%s/class="\zs[^"]*/\=join(map(split(submatch(0)),"(v:val=~'^o-'?'':'o-').v:val"))/

我们有:

(v:val=~'^o-'?'':'o-').v:val

如果元素以o-开头,则我们不再添加其他o-

答案 1 :(得分:3)

一种方法是利用\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