使用Vim查找不以特定字符串开头的行

7

我有一个包含成千上万行的文件,每一行都以日期开头,例如:

2021-02-22... 

但有些奇怪的行并不是以这种方式开始。我的意图是编写一个宏来查找它们,并将它们与上一行连接起来。

我在vim中如何搜索这样的行?

例如,如果我想要在vim中找到下一个匹配的行,我会输入:

/^2021

它会将我带到下一行,该行以“2021”开头。

我想做到这一点,但要查找下一个不匹配的行。


1
这个有帮助吗?https://superuser.com/questions/383939/how-to-do-a-vim-search-inverse-search-for-all-lines-with-out-text - xdhmoore
我不想生成所有不匹配行的列表,我想移动到下一行不匹配的行。就像“/”所做的那样,但是针对不匹配的模式。 - slashdottir
相关:https://dev59.com/xnM_5IYBdhLWcg3wQQvw - jdhao
3个回答

9
我的意图是编写一个宏来查找它们并将它们与上一行连接起来。通常使用`:help :global`执行这种操作。
:g!/<pattern>/<command>

执行<command>在每一行中,不匹配<pattern>的情况下。在您的情况下,它会像这样:
:g!/^2021/-j

这里的意思是:

  • ^2021 是你要匹配的模式(pattern),
  • -j 命令先将地址设置为上一行,然后与下一行合并。

你可能会觉得以下写法更加直观易懂:

:g!/^2021/norm! kJ

这基本上使用了:-j的正常模式等价物。

如果您在文件中有几年的时间,请考虑一个简单的交替方案:

:g!/^\(2021\|2020\|2019\)/-j

或者更普遍的模式:
:g!/^\d\d\d\d-\d\d-\d\d/-j

你不必在这里尝试变得聪明,使用量词和负向回顾等技巧。

参考:

:help :global
:help :range
:help :join
:help :normal
:help k
:help J
:help /^
:help \d
:help /\|
:help /\(

:join 命令与负数范围一起使用是否可行?例如 :g!/^2021/.-1join:v/^2021/-j - Peter Rincker
@PeterRincker :g!/^2021/-j 或者 :v/^2021/-j 都可以,你觉得我应该把它加入我的答案还是你想要发表自己的答案? - romainl
我认为将它添加到您的评论中会是最好的选择。这实际上只是使用 :join 命令,它与普通的 j 非常相似。 - Peter Rincker

5
我们可以在Vim中使用环视正则表达式来解决这类问题。如果我理解正确,您想要搜索不以2021开头的行,对吗?
以下搜索模式可行:
/\v^(2021)@!

对这个搜索的分解:

  • \v:使用魔术搜索,将简化vim正则表达式,参见:h \v
  • ^:匹配行的开头。
  • (2021)@!@!是负向先行断言,即在行首之后,以下模式不应是2021,括号表示一个正则表达式组。

0

这将查找并选择不以 2021 开头的非空行:

/^[^2]\([^0]\([^2]\([^1]\)\?\)\?\)\?.*

解释:

  • [^2] - 期望一个不是 2 的字符
  • 使用嵌套的方式添加其他数字作为可选字符,使用 \([^<d>]\)\?,其中 <d> 表示一个数字

FYI,我还尝试了负回顾和前瞻,例如/^\(\)\@!2021,但是那并没有起作用。 - Peter Thoeny

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