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')?

8
  • 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 ? Commented May 7, 2016 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. Commented May 7, 2016 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... Commented May 7, 2016 at 17:06
  • 1
    You're welcome, considere adding this + some informations as an answer for further reference :) Commented May 7, 2016 at 19:44
  • 1
    @user9433424 you can get around having to use a variable by doing execute "cexpr " . system("...") Commented Aug 23, 2016 at 18:28

1 Answer 1

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*'} 

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.