多个: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