【问题标题】:how to non-capturing search and replace in vim如何在 vim 中进行非捕获搜索和替换
【发布时间】:2016-07-12 13:17:36
【问题描述】:

我正在尝试学习如何在 vim 中使用正则表达式,并且我目前正在尝试进行搜索和替换。我有这样的事情:

aaaaaaa&sometext&...
aaaaaaaanothertext

as 实际上是行首的空格,我不知道如何在这里打印)

我想用& & 替换第一次出现的&,并保持其他所有内容不变。正如here 所建议的那样,我将\%(...\) 用于非捕获模式,但a 模式仍被捕获。我正在使用:%s/\%(^a*\)&/& &/gc,我得到:

aaaaaaaa& aaaaaaaa&sometext&...
aaaaaaaaanothertext

我不明白为什么。我也尝试过用组替换,如:%s/\%(^a*\)\(&\)/\1 \1/gc,但后来我得到:

& &sometext&...
aaaaaaaanothertext

因此,似乎该组确实被组处理忽略了(因为第一个组在搜索模式上是 &),但仍被搜索模式捕获。

所以,长话短说,我必须使用哪个替换命令才能从:

aaaaaaa&sometext&...

到:

aaaaaaa& &sometext&...

?

【问题讨论】:

    标签: regex vim


    【解决方案1】:

    “非捕获”并不意味着您认为它的含义。 \(...\)\%(...\)之间的唯一区别是子表达式是否保存到\1\2...它仍然会在匹配中包含匹配的内容。

    你想要\@<= (:help \@<=):

    :s/\(^a*\)\@<=&/\& \&/g
    

    【讨论】:

      【解决方案2】:

      我想用&amp; &amp; 替换第一次出现的&amp;,并保留 其他一切照旧

      使用替换命令:

      :s/&/& &/
      

      另一个提示:Vim 默认将( 视为文字字符,而不是组的开头。

      如果您希望正则表达式更像传统 (Perl) 正则表达式,请使用 very magic 模式。

      指定very magic 模式的简单方法是使用\v 开始您的正则表达式:

      " this is a no-op
      :s/\v(this is grouped)/\1/
      

      编辑:此答案有效,但请参阅下面@heijp06 非常相关的评论(我不知道&amp; 字符有特殊含义)。

      评论粘贴在这里:

      为什么这个答案是正确的实际上有点不平凡。一个&在 替换的替换部分意味着匹配的内容 本例中的模式是 & 所以最终效果是正确的。

      【讨论】:

      • 很好,谢谢。但我仍然想学习如何使用非捕获组。可以那样做吗?如果有,怎么做?
      • 您是否尝试过使用very magic 模式的示例?或者,转义您的()
      • 我在上面给出的示例中的() 被转义了。 \%(\) 是我启动组的方式,而不是试图与 vim 正则表达式引擎匹配。我尝试过使用very magic,但得到了类似的结果:我尝试:%s/\v(^a*)(\&amp;)/\1 \1/c 并得到aaaaaaaa aaaaaaaasometext&amp;...
      • 我找到了一种令人满意的方法::s/\v(^a*)(\&amp;)/\1\2 \2/c。我没有丢弃第一组,而是在替换模式中重用它。但是,它不使用非捕获组。我尝试过使用 perl 非捕获组模式 (?:...),但我从 vim 收到错误。
      • 为什么这个答案是正确的实际上有点不重要。替换部分中的&amp; 表示与模式匹配的内容在这种情况下是&amp;,因此最终效果是正确的。
      【解决方案3】:

      通常在搜索和替换中,替换完全替换搜索就足够了。在这种情况下,您的搜索将包含您不想替换的内容。

      Vim 有一些有用的模式来定义匹配的开始和结束:\zs\ze。您可以将\zs 放在搜索中的任何位置,vim 只会在开始后匹配。您可以同时使用这两种方式来表示,找到该特定行并仅替换其中的一部分。

      以及解决方案:

      :%s:^[^&amp;]*\zs&amp;:&amp; &amp;:c

      • %s:查看文件中的每一行
      • ^[^&amp;]*:从行首开始,应该有零个或多个 &amp;
      • \zs&amp;:要替换的匹配是单个&amp;
      • &amp; &amp;:将匹配替换为两个&amp;
      • c:以交互方式执行每个替换,以防我对正则表达式不满意

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-15
        • 2011-06-15
        • 2011-11-02
        • 1970-01-01
        • 1970-01-01
        • 2017-01-05
        • 2017-09-21
        • 1970-01-01
        相关资源
        最近更新 更多