The reason the pipe isn't functioning like you'd expect is because you're not grepping through the shell, you're grepping through Vim (see digression). For instance, this would be using your shell from Vim to perform your search:
:!grep -R 'color:' . | grep -v '@'
Note the !
at the beginning, which means "execute this command from the shell" (see :h :!
). This doesn't help your underlying problem, however, because your shell's end result won't go the quickfix list. This simply executes the whole command at the shell, lets you see it, and returns you to Vim.
Your fastest solution might be to employ grep's --exclude
(note: see EDIT below):
:grep -R --exclude='*@*' 'color:' .
Digression: :grep
is different from :!grep
in that Vim is using a file pattern searcher of your choice as an Ex command within Vim, not the shell. The grepprg
option indicates which file pattern searcher to use (use :set grepprg?
to see what's currently set). If you have set grepprg=grep\ -nH
in your .vimrc
, for instance, then :grep
will indeed use grep
. If grepprg
is set to internal
, however, then :grep
will use :vimgrep
instead, which will require a Vim search pattern. (You might be familiar with the Vim search pattern from using /
and ?
.) See :h :grep
and :h :vimgrep
for details. Also, if you like ack or ag, you can set grepprg
to tell :grep
to use them instead of regular grep or vimgrep.
EDIT
@the_velour_fog Thanks for correcting me by pointing out that grep's --exclude
is excluding files to grep, rather than omitting lines that otherwise match grep's search pattern.
One solution is to use Vim script's getqflist()
and setqflist()
to pass searches to the existing quickfix list and populate a new one. See Kent's Stack Overflow answer and resulting QFGrep on GitHub. With this script, you can perform your first grep/ack like normal, then use the following actions:
<Leader>g
input pattern to do further filtering
<Leader>v
input pattern to do further inverted filtering (like grep -v)
<Leader>r
restore the Quickfix/location-list with original entries
:cexpr system("grep -Rn 'color:' . \| grep -v '@'")
If it does, to save some keystrokes you could define the command:CS
like this:command! -nargs=1 CS :cexpr system(<q-args>)
, and then use it like this::CS grep -Rn 'color:' \| grep -v '@'
-n
switch to grep and then vim can parse it into its quicklistsystem()
is just a function to which you can give any shell command as an argument. It sends it to the shell which executes it and then gives you its output.:cexpr
is an Ex command which takes a string or a list as an argument, and parses it to populate the quickfix list. So basically, you're sending your shell command from vim to the shell throughsystem()
and then parse its output through:cexpr
. And yes, you're right, using the-n
switch withgrep
seems necessary for vim to correctly parse the output. In:help cexpr
, they use it in one of their example.:Qgrep
command that allows you to narrow down the quickfix list by a pattern.