How do I pipe a visual selection through an external shell command and replace it with the output?
Answer
:'<,'>!{cmd}
Explanation
After making a visual selection and entering the command line with :, Vim automatically inserts the range '<,'> for the selection. Appending !{cmd} pipes the selected lines through the shell command and replaces the selection with the command's stdout. This turns any external tool into an in-editor transformation.
How it works
'<and'>are marks set automatically for the start and end of the last visual selection!{cmd}is the filter operator — it pipes the addressed lines to the command's stdin, and replaces them with stdout- The visual selection does not need to be active at the time you type the command; the marks persist
Example
Visually select a block of JSON text and format it with jq:
{"name":"Alice","age":30}
Select the line in visual mode, then run:
:'<,'>!jq .
The line is replaced with formatted JSON:
{
"name": "Alice",
"age": 30
}
Tips
- Common uses:
!sort,!sort -u,!column -t,!python3 -m json.tool,!jq .,!fmt,!par !sorton a visual selection sorts only those lines, leaving the rest of the file intact- Combine with
!awkor!sedfor complex in-place transformations - The entire buffer can be filtered with
:%!{cmd}— the visual selection variant lets you target specific blocks - If the command produces an error, Vim shows the error output and does not replace the selection