如何使用子匹配值搜索和替换 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
现在,还有一些小提示:
您可以使用 &
代替 [=21=]
。
使用 \v
开启 magicness 因此您可以删除一些反斜杠(参见 :help /\v
)
因为你只想每行替换一个匹配项,所以不需要在最后加上 /g
。
综上所述,我会推荐以下正则表达式:
:%s/\vid=(.{-})/& name=""
我有 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
现在,还有一些小提示:
您可以使用
&
代替[=21=]
。使用
\v
开启 magicness 因此您可以删除一些反斜杠(参见:help /\v
)因为你只想每行替换一个匹配项,所以不需要在最后加上
/g
。
综上所述,我会推荐以下正则表达式:
:%s/\vid=(.{-})/& name=""