代码之家  ›  专栏  ›  技术社区  ›  T.J. Crowder

如何匹配跳过异常的模式?

  •  1
  • T.J. Crowder  · 技术社区  · 6 年前

    在里面 vim ,我希望在搜索和替换操作中匹配正则表达式,但有例外情况—我希望跳过的匹配列表。

    -一-奥雷姆·伊普苏姆-二-布拉-三-现在是时候了-四-快速棕色-五-等等。

    -\(\w\+\)- 并将其替换为 *\1* -two- -four- ,因此结果将是:

    *一个是lorem ipsum,两个是废话,三个是时间,四个是快速棕色,五个,等等。

    看起来我应该能够使用某种断言(lookbehind,lookahead,something)来处理这个问题,但我现在还是一片空白。

    2 回复  |  直到 6 年前
        1
  •  3
  •   Ingo Karkat    6 年前

    你在找一个 消极前瞻 :help /\@! 喜欢 (?!pattern) 在Perl中。

    基本上,你说 不匹配 FOO :

    /-\(\%(FOO\)\@!\w\+\)-/
    

    注意我是如何使用 非捕获组 :help /\%( ).仍然缺少的是结尾的断言,因此上述内容也将排除在外 -FOOBAR- . 由于这里有一个唯一的结束分隔符,因此最容易附加:

    /-\(\%(FOO-\)\@!\w\+\)-/
    

    /-\(\%(two-\|four-\)\@!\w\+\)-/
    

    或者,通过分解重复的结束分隔符:

    /-\(\%(\%(two\|four\)-\)\@!\w\+\)-/
    

    这将匹配虚线之间的任何单词字符, 除了 two four .

        2
  •  2
  •   Ingo Karkat    6 年前

    这个 消极前瞻 在我的另一个答案中,是直接解决方案,但它的语法有点复杂(并且可能存在一些模式,其中分隔符的规则不是那么简单,结果的可读性要差得多)。

    可供替代的 是将选择逻辑放入 替换 :substitute . Vim允许Vimscript表达式通过 :help sub-replace-expression .

    我们已经把捕获的单词放在地图上了 submatch(1) (相当于 \1 在正常替换中),现在只需要检查两个排除的单词;如果是其中之一,则通过返回原始完整匹配进行无操作替换( submatch(0)

    :substitute/-\(\w\+\)-/\=submatch(index(['two', 'four'], submatch(1)) == -1 ? 1 : 0)/g
    

    它不比前瞻模式短(好吧,我们可以 高尔夫球运动 0 1 ,无论如何),所以在这里我仍然使用该模式。但总的来说,很高兴知道有不止一种方法可以做到这一点:-)