如何在vim中使我的匹配非贪婪?

572

我有一个巨大的HTML文件,里面有很多看起来像这样的标记:

<p class="MsoNormal" style="margin: 0in 0in 0pt;">
  <span style="font-size: small; font-family: Times New Roman;">stuff here</span>
</p>
我正在尝试使用Vim的搜索和替换功能来清除所有class=""style="",但是我在使匹配非贪婪方面遇到了问题。
我的第一次尝试是这样的:
%s/style=".*?"//g

但是Vim似乎不喜欢?。不幸的是,删除?会使匹配过于贪婪。

我该如何让匹配变成非贪婪的?


我认为保罗的答案很好。只是要说明,在vim中,“?”不意味着可选项(如果这是您使用“?”想要实现的效果的话)。 - LB40
16
@LB,在许多语言中,.*?意味着匹配任何字符但要非贪婪匹配。这就是他想要实现的。 - Randy Morris
相关:在 Vim SE 上如何使正则表达式匹配器变为非贪婪模式? - Big McLargeHuge
对于不了解"ungreedy/non-greedy"术语的人:它也被称为"lazy"。 - G Eitan
8个回答

880

.\{-} 替代 .*

%s/style=".\{-}"//g

此外,请参阅 :help non-greedy


56
这个并不是很直观,这只有Vim才做得到吗? - Ehtesh Choudhury
113
每个东西都有自己的正则表达式语言…… 这是使用正则表达式时最大的问题之一。 - Patrick Farrell
46
许多这些工具在同一时期发展壮大并独立地开发了其自己的正则表达式语言方言。许多这些工具也试图解决不同的问题,因此这些实现中的语法可能会有非常大的不同。我们必须接受这就是现实世界的运作方式,尽管有时它会让开发人员的工作更加困难。幸运的是,现在许多工具都至少提供了与Perl兼容的正则表达式实现。不幸的是,Vim不是其中之一。 - Randy Morris
24
如果有人像我一样将搜索默认设置为\v(非常魔法标志),那么您需要使用.{-} - jgillman
66
@Shurane @Ziggy Mnemonic: 控制重复次数,就像 {1,3}(大括号)一样。减号“-”的意思是:尽可能少地重复,(少==减)。 ;) - Ciro Santilli OurBigBook.com
显示剩余7条评论

72

在vim中,使用{-}运算符可以进行非贪婪搜索。像这样:

%s/style=".\{-}"//g

只是尝试:

:help non-greedy

49

有什么问题

%s/style="[^"]*"//g

10
虽然出于自己的利益,我仍然希望更好地理解不贪婪的事情。 - Mark Biek

20

如果你更习惯使用PCRE正则表达式语法,该语法:

  1. 支持非贪婪操作符?,就像你在OP中所要求的;
  2. 不需要对分组和基数运算符进行转义(这是一种完全不直观的vim语法要求,因为你不是匹配文字,而是指定运算符);
  3. 你的[g]vim已编译具有perl功能,请使用

    :ver命令检查特性;如果存在+perl,你可以开始使用)

尝试使用搜索/替换功能。

:perldo s///

示例:交换img标记中的src和alt属性:

示例。在img标记中交换src和alt属性:

Example. 交换img标记中的src和alt属性:

<p class="logo"><a href="/"><img src="/caminoglobal_en/includes/themes/camino/images/header_logo.png" alt=""></a></p>

:perldo s/(src=".*?")\s+(alt=".*?")/$2 $1/

<p class="logo"><a href="/"><img alt="" src="/caminoglobal_en/includes/themes/camino/images/header_logo.png"></a></p>

1
perldo 的功能非常好,但不幸的是在输入正则表达式时无法突出显示所选的测试。 - mljrg
你不能像使用本地vim替换s/一样使用perldo进行交互式正则表达式查找/替换。或者这是可能的吗?我很想错。 - Z4-tier

14
我发现针对这类问题的一个好解决方法是:
:%!sed ...
(或者使用 perl,如果你更喜欢的话)。换句话说,不要学习 vim 的正则表达式特性,而是使用你已经熟悉的工具。使用 perl 可以使 ? 修饰符起到非贪婪匹配的作用。

2
不错的观点,但在应用正则表达式之前能够使用/pattern来检查匹配模式是否正确,并在vim正则表达式中使用c修饰符也很好 :) - João Portela
这是正确的。所有这里的解决方案都不接近非贪婪!如果您必须在包含大量文本和几个该模式的出现的行中匹配[0-9] \ {7},则此处的任何解决方案都无法实现。这里的解决方案仅适用于简单的事情(公平地说,这就是所要求的)。但是,如果您需要做更多的事情而不仅仅是搜索下一个引号,vim将无法帮助您。 - gcb

5

根据几个评论的建议,可以使用\v来实现

:%s/\v(style|class)\=".{-}"//g

4

插件 eregex.vim 处理 Perl 风格的非贪婪操作符 *?+?


@xsilenT https://github.com/othree/eregex.vim: "建议使用Vundle或Pathogen安装脚本。" - eXe
很抱歉,我不知道如何使用 Vundle 或 pathogen。 - xsilen T

-3

你好,

Vim的正则表达式处理能力不太强。我发现sed的正则表达式语法与vim的能力相当匹配。

通常我会打开搜索高亮功能(:set hlsearch),然后在输入斜杠进入搜索模式后调整正则表达式。

编辑:马克,最小化贪婪匹配的技巧也在Dale Dougherty的优秀著作“Sed & Awk”(sanitised Amazon link)中有所涉及。

第三章“理解正则表达式语法”是一个关于sed和awk所涉及的更原始的正则表达式能力的优秀介绍。只需短时间阅读,强烈推荐。

希望对你有所帮助。

祝好,


8
Vim的正则表达式处理其实非常好用。它可以做到sed做不到的事情,比如可以根据行/列号匹配或根据字符在不同语言中的分类(关键字、标识符或空白符)进行匹配。此外,它还有零宽度断言和在替换的右侧放置表达式的能力。如果使用\v,可以大大简化语法。 - Brian Carper
1
@Brian,谢谢。我会做一个帮助正则表达式,看看我错过了什么。 - Rob Wells
@RobWells,《Sed & Awk》这本书在我看来确实非常好,但没有明确讨论贪婪/懒惰量词。作为证据,这本书中绝对没有出现过“greed”或“greedy”这些词,只有一个与此无关的“lazy”一词出现了一次。 - Enlico
@EnricoMariaDeAngelis,这个例子确实是关于如何使用“非”运算符来实现非贪婪匹配的。但它并没有明确提到这个术语。贪婪和懒惰这两个术语是在Perl的NFA引擎中引入操作符来特别修改贪婪匹配行为时出现的。 - Rob Wells

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接