在一个语句中有多个:g和:v命令

Dog*_*ert 14 vim

我有这个文件

foo
foo bar
foo bar baz
bar baz
foo baz
baz bar
bar
baz
foo 42
foo bar 42 baz
baz 42
Run Code Online (Sandbox Code Playgroud)

我想要

  1. 选择包含foo但不包含的行bar
  2. 删除包含foo和不包含的行bar

我在某处读到(找不到链接)我必须使用:exec with |this.

我尝试了以下,但它不起作用

:exec "g/foo" # works
:exec "g/foo" | exec "g/bar" -- first returns lines with foo, then with bar
:exec "g/foo" | :g/bar -- same as above
Run Code Online (Sandbox Code Playgroud)

当然,如果我不能选择一条线,我就无法执行normal dd.

有任何想法吗?

编辑

赏金注意事项:

我正在寻找一个使用正确的解决方案:g和:v命令,并且不使用正则表达式黑客,因为条件可能不一样(我可以有2个包含,3个排除).

另请注意,最后两个不起作用的例子,它们只能删除行,但是当我运行它们而不删除(即查看所选行)时它们会返回不正确的信息,并且它们的行为如上所述.

Zec*_*ecc 10

我不是vim向导,但如果您要做的只是"删除包含foo并且不包含bar的行",那么这应该做(我试过你的示例文件):

:v /bar/s/.*foo.*//
Run Code Online (Sandbox Code Playgroud)

编辑:实际上这留下了空行.您可能希望为第二个搜索模式添加可选换行符.

  • 更改为..*foo.*\n`以删除换行符. (3认同)

Con*_*ner 4

这对您来说可能仍然很麻烦,但是您可以编写一些 vim 脚本来为此创建一个函数和专用命令。例如:

command! -nargs=* -range=% G <line1>,<line2>call MultiG(<f-args>)
fun! MultiG(...) range
   let pattern = ""
   let command = ""
   for i in a:000
      if i[0] == "-"
         let pattern .= "\\(.*\\<".strpart(i,1)."\\>\\)\\@!"
      elseif i[0] == "+"
         let pattern .= "\\(.*\\<".strpart(i,1)."\\>\\)\\@="
      else
         let command = i
      endif
   endfor
   exe a:firstline.",".a:lastline."g/".pattern."/".command
endfun
Run Code Online (Sandbox Code Playgroud)

这将创建一个命令,允许您自动执行“正则表达式黑客”。这样你就可以做到

:G +foo -bar
Run Code Online (Sandbox Code Playgroud)

获取所有带有 foo 而不是 bar 的行。如果参数不是以+或开头-,则将其视为添加到:g命令末尾的命令。所以你也可以这样做

:G d +foo -bar
Run Code Online (Sandbox Code Playgroud)

删除这些行,甚至

:G norm\ foXp +two\ foos -bar
Run Code Online (Sandbox Code Playgroud)

如果你逃离你的空间。它还需要一个范围,例如:1,3G +etc, 并且您可以在搜索词中使用正则表达式,但必须转义空格。希望这可以帮助。