I want to select a block of text (for example, V%
) and use the text as input to a shell command (for example, wc
or pbcopy
) - but I don't want to alter the current buffer - I just want to see the output of the command (if any) then continue editing without any changes.
Typing V%!wc
translates to :'<,'>!wc
and switches the block of text for the output of the wc
command.
How do you pipe a chunk of text to an arbitrary shell command without affecting the current buffer?
You can run commands in Vim by entering the command mode with : . Then you can execute external shell commands by pre-pending an exclamation mark ( ! ). For example, type :! ls , and Vim will run the shell's ls command from within Vim.
You can run the shell commands from inside of Vim by just using :! before the command, : means you have to be in command mode. Just after being in command mode, the ! or bang operator will execute the command typed after it from the terminal(Linux/ macOS) or your default shell(Windows -> CMD/Powershell).
Select your block of text, then type these keys :w !sh
The whole thing should look like:
:'<,'>w !sh
That's it. Only took me 8 years to learn that one : )
note: typing : after selecting text produces :'<,'> a range indicating selection start and end.
Update 2016: This is really just one use of the generic:
'<,'>w !cli_command
Which basically lets you "send" arbitrary parts of your file to external commands and see the results in a temporary vi window without altering your buffer. Other useful examples would be:
'<,'>w !wc '<,'>w !to_file my_file
I honestly find it more useful to alter the current buffer. This variety is simply:
'<,'>!wc '<,'>!to_file my_file
One possibility would be to use system()
in a custom command, something like this:
command! -range -nargs=1 SendToCommand <line1>,<line2>call SendToCommand(<q-args>) function! SendToCommand(UserCommand) range " Get a list of lines containing the selected range let SelectedLines = getline(a:firstline,a:lastline) " Convert to a single string suitable for passing to the command let ScriptInput = join(SelectedLines, "\n") . "\n" " Run the command let result = system(a:UserCommand, ScriptInput) " Echo the result (could just do "echo system(....)") echo result endfunction
Call this with (e.g.):
:'<,'>SendToCommand wc -w
Note that if you press V%:
, the :'<,'>
will be entered for you.
:help command :help command-range :help command-nargs :help q-args :help function :help system() :help function-range
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With