There's a shell solution for your issue and a Vim solution to it.
Shell solution
The shell solution to your issue is to have the shell read the contents (two lines with hello
and \bworld
) from standard input, then assemble the echo -e ...
command and execute it.
You can do so using the shell's eval
command, to reinterpret the assembled string as a shell command. You can use $(cat)
to capture the standard input as a string in the command to be eval
uated.
:w !eval 'echo -e "'"$(cat)"'"'
Note that this is a concatenation of three strings, first being echo -e "
, including the opening double quote and the last being a single double quote. The middle one "$(cat)"
is itself inside double quotes in order to preserve spaces and newlines (that's before eval
has a run on it.) Note that this solution is fragile, as if your input has any "
s in it, it will potentially break the command. But it's the closest one to your original example and to what you specified.
Vim solution
A solution within Vim is to use the :!
command instead and assemble the shell command, in this case echo
, inside Vim itself.
You can use :execute
to run the command from a Vim string, and shellescape()
to quote the argument to echo
. Note that in this case you'll need to pass a non-zero second argument to shellescape()
, so it escapes the newlines with a backslash, which makes it work correctly with :!
.
First yank the visual selection into the default register with a y
command.
Then execute the external command with:
:execute '! echo -e '.shellescape(@", 1)
(Here @"
is the default register.)
This solution is quite robust to characters in the input, since shellescape()
is doing the job of escaping special characters and quoting the string. (Note how we don't have any "
s or '
s that are passed to the shell, those are only Vim strings here.)
There's a small difference in how Vim runs :w !{cmd}
and :!{cmd}
here, in that with the former it doesn't clear the screen (switch back from the alternate screen) but does so with the latter.
One hacky workaround is to still use :w !{cmd}
for the second case, perhaps with a small range of the current line. It will pass the external command that line as standard input, but as long as the command doesn't use the standard input, that shouldn't make a difference.
:execute '.w !echo -e '.shellescape(@", 1)
some_command -some_flag "selection_from_vim"
?vim
, you just need to make sure your shell command can read input fromstdin
.vim
related.