Since I posted this the title of the question was changed to explicitly reference arguments. Just in case someone gets the idea that I have reading comprehension issues... ;)
To send multiple lines of Visually selected text to a shell command I'd do it this way:
:vnoremap XXX :w !<shell command><CR>
If you enter :
when text is selected you'll see that the range of lines that are selected is inserted automatically. The same things happens with vmappings so you only need to specify the :
then w!
(which will send the lines in the current range to a shell program) followed by your shell script path.
As long as your script knows how to process stdin it should be fine.
As a simple example suppose this is my mapping:
vnoremap <Leader>X :w !tac<CR>
(Shell commmand tac
reverses whatever text it receives from stdin.)
If I've visually selected these lines:
aaa
bb
c c
...and hit <leader>X
then I'll see
c c
bb
aaa
If you aren't able to leverage stdin and can only use command args that's much stickier. Bash and friends are notoriously tricky when it comes to how white space is handled on the command line (i.e. due to globbing and word splitting). The Vim functions system()
and shellescape()
will help but unless the types of data you will be sending are relatively constrained you may still have to work at it to get it right. Thus, if you can manage without args and use stdin you really should favor that. (If you didn't have the multi-line input requirement things would be a little easier.)