Reputation: 5067
I am trying to process a series of files. I have noticed that there are discrepancies in running a particular command from the command line (i.e. ex
mode). E.g.
$cat poo.txt
big
red
dog
small
black
cat
$vim -c "2,$g/^dog/d|wq" poo.txt
$cat poo.txt
big
small
black
cat
It appears that 2,$g/^dog/d|wq
has deleted the lines with red
and dog
. This confuses me because the command should : start on line 2 (going to EOF) and delete all lines beginning with dog
. In this instance, I'd expect the output to be:
$ cat poo.txt
big
red
small
black
cat
In fact, if I try this in the vim editor this is the exact behavior that is observed.
QUESTION: What is cause of the discrepancy between the vim -c
version and the vim
version of running this command?
Upvotes: 4
Views: 605
Reputation: 1750
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
Upvotes: 3