【问题标题】:How to delete all paragraphs where a pattern is not present?如何删除不存在模式的所有段落?
【发布时间】:2013-08-29 09:40:47
【问题描述】:

我保留了我参加的会议的日志。

每次会议:

  • 由空行分隔(->每个会议都是一个段落)
  • 由于表达式而折叠
  • 包含一行和相应的标签:ACME、GMBH、SARL 等……

当我想回顾我参加过的所有会议时,例如 ACME,

  • 我创建了一个暂存缓冲区(:%y,后跟 :tabnew,然后是粘贴)
  • 并且我希望删除所有 ACME 不存在的段落。

这就是我有问题的地方。

我知道如何按行搜索/删除:

:v/ACME/d

但是我如何按段落来做到这一点(以便将整个段落保持在 ACME 的位置,而不是唯一的标签行)?

注意:模式 ACME 可以在这些段落中出现不止一次。

【问题讨论】:

    标签: vim


    【解决方案1】:

    这行得通:

    let @r="" | execute("g/acme/ normal \"Rdap") | %d | put r
    

    它去每个包含“acme”的段落,并删除它附加注册r。然后删除所有内容并放入寄存器 r。

    如您所见,基本技巧是使用大写字母寄存器添加,而不是替换其内容。这也需要在开始时重置寄存器,以丢弃之前的寄存器内容。

    这适用于多次出现“acme”的段落,因为整个段落在第一次匹配后被删除,因此不再匹配。

    【讨论】:

    • 哇,带括号的execute 没有给出语法错误真的很惊讶。我以前从未见过这个,它通常写成execute "..."
    • @glts 在这里也一样! ;) 我什至搜索了:h execute() 以查看是否有功能.. 无论如何,这可以工作+1!如果一开始保存@r的值并在最后恢复它会更好。
    • @glts 我也试过 echo ("foobar")echo ("foo").("bar") 工作。似乎只要()之间的表达式返回一个有效的字符串(或者可以转换成str),它就可以工作。 ( and ) 增强了可读性。 :)
    • @eleom :效果很好,所以我接受答案并添加 +1 !只有一个(次要)问题:你怎么不使用,在那种情况下 v 而不是 g ?
    • @ThG 使用:g 可以定位每个“acme”事件。对于每个“acme”事件,您都会得到包含的段落。因此,您可以将包含“acme”的段落与不包含“acme”的段落分开。如果你以另一种方式开始(:v),你会得到每一行没有“acme”的行。这些行可能出现在任何类型的段落中(包含“acme”的段落和不包含“acme”的段落)。所以,这条路不会带你到任何地方。
    【解决方案2】:

    我会用 awk 来做,在 vim 中你可以:

    %!awk -v RS="" -v ORS="\n\n" '/ACME/' 
    

    那么只会保留包含ACME 的段落。

    【讨论】:

    • 感谢您的回答,但我的 Android 设备上没有 awk(仅在我的计算机上)。单用 Vim 是不可能的吗?
    • 我试过 :v/'{ACME'}/d ... 并删除了所有内容(我仍然不明白为什么)。再次感谢。
    • @ThG :v 和 :g 不起作用,因为它们会line明智地处理文本
    • 好的,我现在明白这并不容易......无论如何谢谢
    猜你喜欢
    • 2018-09-26
    • 1970-01-01
    • 2016-09-30
    • 1970-01-01
    • 1970-01-01
    • 2017-03-05
    • 2022-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多