如何使用子匹配值搜索和替换 Vim

How to search and replace in Vim with submatch values

我有 HTML 看起来像这样

<form>
  <input id="firstname" value=""/>
  <input id="lastname" value=""/>
  <input id="email" value=""/>
</form>

我想将 name="{id-name}" 添加到每个输入字段(请参见下面的示例代码)

<form>
  <input id="firstname" name="firstname" value=""/>
  <input id="lastname" name="lastname" value=""/>
  <input id="email" name="email" value=""/>
</form>

如何使用 Vim 执行此操作?

我正在努力

%s/id=".*"/\=submatch(0)/g

这会导致两个问题:

1) 搜索,从第一句到最后一句搜索。它应该从第一个报价搜索到下一个报价。

2.) submatch(0) 正在获取完整的搜索结果。我怎样才能将它隔离到 id="{value}"?

之间的值

我经常遇到这个问题,弄清楚这个 vim 命令可以帮助我在未来节省很多时间。主要是将搜索结果拆分到 submatch() 我也看到堆栈上的人使用 而不是 submatch() 来存储结果,这种方法更好吗?

任何帮助将不胜感激!谢谢!

我的第一个想法是这个问题更适合 the Vim Stack Exchange...

不过我还是会在这里回答的


您遇到的第一个问题叫做贪婪。基本思想是 * 量化是 greedy,因此它会尝试匹配尽可能多的文本。更深入的解释可以是found here.

要解决此问题,您可以简单地使用 * 的非贪婪等价物,即 \{-}。由于这是非贪婪的,它会尝试匹配尽可能少的文本。例如,看看这段文字:

"hello", "world", "test"

运行

:s/".*"

将删除所有内容,但

:s/".\{-}"

只会删除 "hello"

要解决第二个问题,您需要查看捕获组。基本上,括号中的任何内容都将被放入第 1 组,然后下一对括号将被放入第 2 组,依此类推。默认情况下,整个匹配模式都放在组 0 中。

我还建议 不要 使用 eval 运算符,即 \=。这使事情不必要地冗长。您的示例完全等同于

:%s/id=".*"/[=13=]/g

因为[=21=]表示第0组,</code>表示第1组,依此类推</p> <p>所以你可以这样做:</p> <pre><code>:%s/id="\(.\{-}\)"/[=14=] name=""/g

现在,还有一些小提示:

  1. 您可以使用 & 代替 [=21=]

  2. 使用 \v 开启 magicness 因此您可以删除一些反斜杠(参见 :help /\v

  3. 因为你只想每行替换一个匹配项,所以不需要在最后加上 /g

综上所述,我会推荐以下正则表达式:

:%s/\vid=(.{-})/& name=""