I think you need to replace the double quotes with single quotes to prevent your shell from expanding $g
. From man bash
:
Enclosing characters in double quotes preserves the literal value of all
characters within the quotes, with the exception of $, `, \, and,
when history expansion is enabled, !.
Currently, your shell expands $g
inside your string, as if it was an environment variable. But it's probably not defined, thus expands into an empty string. So, even though you've typed:
vim -c "2,$g/^dog/d|wq" poo.txt
Vim doesn't receive the command:
2,$g/^dog/d|wq
... but:
2,/^dog/d|wq
This command deletes all the lines from the one whose address is 2
, to the next one which starts with dog
(in your case it's the 3rd line). Then, it saves and quit.
But even if you replace the quotes, there's still a problem in your command.
From :h :bar
:
These commands see the '|' as their argument, and can therefore not be
followed by another Vim command:
...
:global
...
The bar is interpreted by :g
as a part of its argument, not as a command termination. In your case, it means that whenever it finds a line starting with dog
, it will delete it, then immediately save and quit. So, if there are several dog
lines, only the first one will be deleted, because :g
will have saved and quit after processing the 1st one.
You need to hide |wq
from :g
, either by wrapping the global command inside a string and executing it with :execute
, or by moving wq
in another -c {cmd}
. All in all, you could try:
vim -c 'exe "2,\$g/^dog/d" | wq' poo.txt
or
vim -c '2,$g/^dog/d' -c 'wq' poo.txt
or
vim -c '2,$g/^dog/d' -cx poo.txt