Vim - 像标签一样或仅在模式内替换

时间:2013-01-14 11:59:23

标签: regex vim sed labels

在一些html编辑的基础上,我想出了一些VIM主人的帮助。

我不想完成简单的任务 - 我的html文件包含错误的网址。

<a href="http://some/wrong/url with variable number of spaces">Just description</a> <a href="http://some/wrong/url with three spaces">Just description</a>
...
<a href="http://anoter/wrong/url with completely other number of spaces">Just description</a>

不幸的是,它不是“每行一个网址”。

我知道三种方法:

  1. 我希望能够仅在'"http://[^"]*"'正则表达式中进行替换(类似于仅在匹配行中替换 - 但这次不是整行但只涉及匹配模式)

    < / LI>
  2. 或使用类似sed的标签 - 我可以使用sed -e执行此任务:a -e 's#\("http://[^" ]*\) \([^"]*"\)#\1_\2#g;ta'

  3. 我也知道有类似"\@<="的内容,但我不是母语人士,而且这是我无法理解的手册。

  4. 非常感谢所有帮助。

    如果可能的话,我想知道所有三个问题的答案(因为这些问题非常有趣并且对其他任务有帮助),但其中任何一个都可以。

2 个答案:

答案 0 :(得分:3)

Re:1。您可以通过将vim的“使用表达式评估替换”功能(:h :s\=)与substitute函数(:h substitute())相结合来递归替换:

:%s!"http://[^"]*"!\=substitute(submatch(0), ' ', '_', 'g')!g

回复:2。我不知道sed所以我无法帮助你。

回复:3。我看不出\@<=在这里会有什么帮助。至于它的作用:它相当于Perl的(?<=...)功能,也被称为“积极的后视”。您可以将其读作“如果前面有”:

:%s/\%(foo\)\@<=bar/X/g

“将bar替换为X,如果前面有foo”,即将每foobar转为fooX\%( ... \)只是s/(?<=foo)bar/X/g; 在这里分组)。在Perl中你会把它写成:

{{1}}

更多示例和说明可在perldoc perlretut中找到。

答案 1 :(得分:1)

我认为您要做的是将http:// url中的所有空格替换为_

为了实现这一目标,@ melpomene的解决方案非常简单。你可以在vim中试试。

另一方面,如果你想模拟你的sed线,你可以尝试以下。

:let @s=':%s#\("http://[^" ]*\)\@<= #_#g^M'

^M means Ctrl-V then Enter

然后

200@s

这与sed行(标签,替换,返回标签......)的工作方式相同,并且也使用了@<=

一个问题是,这样,vim无法检测何时更换了所有匹配模式。因此给出了一个相对较大的数字(在我的例子中为200)。最后一个错误消息“E486:Pattern not found ...”显示。

需要一个脚本来避免消息。