5

If I type:

:echo system('grep -IRn foobar ~/.vim | grep -v backup')

Vim displays the output of the shell command:
$ grep -IRn foobar ~/.vim | grep -v backup

Which is the list of files containing the pattern foobar inside the folder ~/.vim, after removing the matches containing the pattern backup.


:echo expand('`grep -IRn foobar ~/.vim | grep -v backup`')

Vim does the same thing (without the newline at the end).


:e `=system('grep -IRn foobar ~/.vim | grep -v backup | tail -1 | cut -d: -f1')`

Vim edits the last file from the output of the previous shell command.


The last 3 commands work without escaping the pipe. The latter is never interpreted as a command termination, probably because it's protected by the string. Maybe for the same reason this command works:

:echo 'hello | world'

But If I want to populate the quickfix list with the same shell command and I type:

:cexpr system('grep -IRn foobar ~/.vim | grep -v backup')

I have the following errors:

E115: Missing quote: 'grep -IRn foobar ~/.vim 
E116: Invalid arguments for function system('grep -IRn foobar ~/.vim 
E15: Invalid expression: system('grep -IRn foobar ~/.vim 

It seems that the pipe was interpreted as a command termination, and that it must be escaped:

:cexpr system('grep -IRn foobar ~/.vim \| grep -v backup')

The pipe is inside a string, and the command is almost identical to the first one with :echo where the pipe is not escaped.

Why is it suddenly interpreted as a command termination with :cexpr system('shell cmd')?

  • 2
    Strange error, for what it's worth, can you confirm that if you do let a='grep -IRn foobar ~/.vim | grep -v backup' and then :cexpr system(a) it works ? – nobe4 May 7 '16 at 16:45
  • 1
    I suspect that for cexpr, the | is used to delimit the vim expression, and not the system one. so vim try to run cexpr system('grep -IRn foobar ~/.vim and then grep -v backup'), which of course fail. – nobe4 May 7 '16 at 16:53
  • 1
    I thought I found something looking at :h :bar, it seems that there are special cases for |, but unfortunately it does not match your problem... – nobe4 May 7 '16 at 17:06
  • 1
    You're welcome, considere adding this + some informations as an answer for further reference :) – nobe4 May 7 '16 at 19:44
  • 1
    @user9433424 you can get around having to use a variable by doing execute "cexpr " . system("...") – Ingo Aug 23 '16 at 18:28
2

This was changed in 8.1.2401; now a shell pipe character does not need to be escaped anymore inside an expression containing a quoted shell command after :cexpr and the five other variants:

:cgetexpr
:caddexpr
:lexpr
:lgetexpr
:laddexpr

Before the patch, an unescaped shell pipe would raise E115 and E116:

$ vim -Nu NONE
:cexpr system('grep -Rn grail '..$VIMRUNTIME..' | grep -v tag')
E115: Missing quote: '
E116: Invalid arguments for function system('grep -Rn grail '..$VIMRUNTIME..'

Now, the same command edits the file $VIMRUNTIME/doc/index.txt, and populates the quickfix list with this entry:

{'lnum': 1121,
 'bufnr': 2,
 'col': 0,
 'pattern': '',
 'valid': 1,
 'vcol': 0,
 'nr': -1,
 'type': '',
 'module': '',
 'text': 'You found it, Arthur!                         *holy-grail* *:smile*'}
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.