我怎样才能让我的比赛在 vim 中不贪心?

Posted

技术标签:

【中文标题】我怎样才能让我的比赛在 vim 中不贪心?【英文标题】:How can I make my match non greedy in vim? 【发布时间】:2010-11-21 07:24:18 【问题描述】:

我有一个很大的 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 中是可选的(如果这是您想要使用“?”实现的) @LB,在多种语言中,.*?表示匹配任何字符但不贪心。这就是他正在努力实现的目标。 相关:How to make regex matchers non-greedy? 在 Vim SE 上。 对于不知道 ungreedy/non-greedy 这个词的人:它也被称为懒惰 【参考方案1】:

.\-代替.*

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

另外,请参阅:help non-greedy

【讨论】:

不是很直观,这是只有vim才有的东西吗? 一切都有自己的正则表达式语言......这是正则表达式最大的问题之一。 许多这些工具在同一时间成熟并独立开发了自己的正则表达式语言方言。其中许多工具还试图解决不同的问题,因此语法在这些实现中可能 - 可能非常不同 - 是有道理的。我们必须接受现实世界就是这样运作的,尽管它有时会让我们作为开发人员的生活更加艰难。幸运的是,如今许多工具至少提供了与 Perl 兼容的正则表达式实现。不幸的是,Vim 不是其中之一。 如果像我这样的人将他们的搜索默认为\v(非常神奇的标志),你会想要使用.- @Shurane @Ziggy Mnemonic:控制重复次数,如1,3 所做的(大括号)。减号- 表示:尽可能少地重复(小==减号);)【参考方案2】:

vim 中的非贪婪搜索是使用 - 运算符完成的。像这样:

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

试试吧:

:help non-greedy

【讨论】:

【参考方案3】:

怎么了

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

【讨论】:

虽然,为了我自己的利益,我还是想更好地理解贪婪的东西。【参考方案4】:

如果你更习惯 PCRE 正则表达式语法,那

    支持非贪婪运算符 ?,正如您在 OP 中所问的那样;和 不需要反向分组和基数运算符(一个完全违反直觉的 vim 语法要求,因为你不是匹配文字字符而是指定运算符);和

    你已经用 perl 特性编译了 [g]vim,使用测试

    :验证和检查功能;如果有 +perl,你就可以走了)

尝试使用搜索/替换

:perldo s///

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

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

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

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

【讨论】:

perldo 效果很好,但遗憾的是在输入正则表达式时没有突出显示选定的测试。 你不能使用 perldo 进行交互式正则表达式查找/替换,就像你可以使用原生 vim 替代 s/ 一样。或者有可能吗?我很想错了。【参考方案5】:

我发现这类问题的一个很好的解决方案是:

:%!sed ...

(如果您愿意,也可以使用 perl)。 IOW,而不是学习 vim 的正则表达式特性,使用你已经知道的工具。使用 perl 会使 ?修饰符的作用是取消匹配。

【讨论】:

好点,但是能够在应用它之前使用/pattern 来检查你是否正确匹配了模式并在你的vim正则表达式中使用c修饰符也很好:)跨度> 这是正确的。这里的所有解决方案都不是非贪婪的!如果您必须匹配 [0-9]\7 在一行中包含大量文本并且该模式多次出现,那么这里没有解决方案。这里的解决方案只适用于简单的事情(公平地说,这是所要求的)。但如果你只是搜索到下一个引用,vim 将无济于事。【参考方案6】:

使用\v(在几个 cmets 中建议)

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

【讨论】:

【参考方案7】:

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

【讨论】:

@xsilenT github.com/othree/eregex.vim : "建议使用Vundle或病原体安装脚本。" 抱歉,我不知道如何使用 Vundle 或病原体。【参考方案8】:

生日,

Vim 的正则表达式处理不是很出色。我发现 sed 的正则表达式语法与 vim 的功能非常匹配。

我通常将搜索高亮设置为 (:set hlsearch),然后在输入斜线后使用正则表达式进入搜索模式。

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

第三章“理解正则表达式语法”很好地介绍了 sed 和 awk 所涉及的更原始的正则表达式功能。只是简短的阅读,强烈推荐。

HTH

干杯,

【讨论】:

Vim 的正则表达式处理实际上相当不错。它可以做 sed 不能做的事情,比如匹配行号/列号或基于每个语言的字符分类作为关键字或标识符或空格进行匹配。它还具有零宽度断言和将表达式放在替换右侧的能力。如果你使用\v,它有助于清理语法。 @Brian,干杯。我会做一个帮助正则表达式,看看我错过了什么。 @RobWells, Sed & Awk 确实是一本非常好的书恕我直言,没有明确在贪婪/懒惰的量词上花费任何文字。作为证明,书中绝对没有出现greedgreedy这两个词,只有一个但不相关的lazy. @EnricoMariaDeAngelis 确实如此,但该示例并未明确提及该术语。它是关于如何定制您的正则表达式以使用“非”运算符来实现非贪婪匹配。当 Perl 的 NFA 引擎引入运算符来专门修改贪婪匹配行为时,贪婪和懒惰这个术语就出现了。

以上是关于我怎样才能让我的比赛在 vim 中不贪心?的主要内容,如果未能解决你的问题,请参考以下文章

CF735C 数论平衡树叶子节点的最大深度贪心斐波那契条件归一化

URAL 2021 Scarily interesting! (贪心+题意)

cqyz oj | 潜水比赛 | 贪心

为啥非贪心量词有时在 Oracle 正则表达式中不起作用?

hdu-1055(贪心)

hdu1052 Tian Ji -- The Horse Racing---田忌赛马贪心