如何使用子匹配值

时间:2017-04-24 17:46:21

标签: linux vim terminal vi

我的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)搜索,从第一个报价到最后一个报价进行搜索。它应该从第一个引号搜索到下一个引用。

enter image description here

2。)submatch(0)正在取得搜索的全部结果。如何将其仅隔离id="{value}"

之间的值

我经常遇到这个问题,弄清楚这个vim命令可以帮助我节省很多时间。主要是将搜索结果拆分为submatch()我还看到堆叠中的人使用\1 \2代替submatch()来存储结果,这种方法更好吗?

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

1 个答案:

答案 0 :(得分:5)

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

但我会在这里回答

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

要解决此问题,您只需使用*的非贪婪等效项,即\{-}。由于这不是贪婪的,它会尝试尽可能少地匹配文本。例如,看看这个文本:

"hello", "world", "test"

运行

:s/".*"

将删除所有内容,但

:s/".\{-}"

只会移除"hello"

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

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

:%s/id=".*"/\0/g

由于\0表示组0,\1表示组1等,

所以你可以这样做:

:%s/id="\(.\{-}\)"/\0 name="\1"/g

现在,还有一些小技巧:

  1. 您可以使用&代替\0

  2. 使用\v启用魔力,以便删除一些反斜杠(请参阅:help /\v

  3. 由于您只想每行替换一个匹配项,因此不需要将/g放在最后。

  4. 总而言之,我建议使用以下正则表达式:

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