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

我有这个文件

foo
foo bar
foo bar baz
bar baz
foo baz
baz bar
bar
baz
foo 42
foo bar 42 baz
baz 42

我要

  • 选择包含foo并且不包含bar
  • 删除包含foo并且不包含bar
  • 我在某处阅读(无法找到链接),我必须使用:exec with | 为了这。

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

    :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
    

    而且,如果我不能选择一条线,我不能在它上面执行normal dd

    有任何想法吗?

    编辑

    赏金注意事项:

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

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


    这对你来说可能仍然是个黑客,但你可以写一些vimscript来为此做一个函数和专门的命令。 例如:

    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
    

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

    :G +foo -bar
    

    得到所有与富而不是酒吧的线。 如果参数不是以+-开始,那么它被认为是添加到:g命令结尾的命令。 所以你也可以这样做

    :G d +foo -bar
    

    删除行,甚至

    :G norm foXp +two foos -bar
    

    如果你逃脱你的空间。 它也需要一个范围,如:1,3G +etc ,你可以在搜索条件中使用正则表达式,但你必须逃避你的空间。 希望这可以帮助。


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

    :v /bar/s/.*foo.*//
    

    编辑:实际上这留下了空行。 你可能想要添加一个可选的换行符到第二个搜索模式。


    这是正则表达式有点麻烦的地方。 您需要使用零宽度匹配(search_string)@= 。 如果search_string任意顺序匹配项目列表, search_string应以.*开头(因此每次从该行的开始处开始匹配)。 要匹配不存在的情况,请使用@! 代替。

    我认为这些命令应该做你想做的(为了清晰起见,我使用#作为分隔符,而不是通常的/ ):

  • 选择包含foo和bar的行:

    :g#(.*foo)@=(.*bar)@=

  • 选择包含foo,bar和baz的行

    :g#(.*foo)@=(.*bar)@=(.*baz)@=

  • 选择包含foo的行并且不包含bar

    :g#(.*foo)@=(.*bar)@!

  • 删除包含foo和bar的行

    :g#(.*foo)@=(.*bar)@=#d

  • 删除包含foo的行并且不包含bar

    :g#(.*foo)@=(.*bar)@!#d

  • 链接地址: http://www.djcxy.com/p/49503.html

    上一篇: Multiple :g and :v commands in one statement

    下一篇: move the text after the cursor to a new line