Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute shell command without filtering from Vim

Tags:

shell

vim

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?

like image 570
searlea Avatar asked Aug 06 '09 09:08

searlea


People also ask

How to execute shell command from Vim?

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.

How do I open a shell in 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).


2 Answers

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 
like image 134
pixelearth Avatar answered Oct 12 '22 01:10

pixelearth


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 
like image 39
DrAl Avatar answered Oct 12 '22 02:10

DrAl