vimtricks.wiki Concise Vim tricks, one at a time.

How do I pipe a range of lines through an external command and replace them with the output?

Answer

!{motion}{command}

Explanation

The ! operator filters the text covered by a motion through an external shell command, replacing the original lines with the command's stdout. This turns Vim into a powerful text pipeline — you can sort, format, encode, or transform arbitrary ranges of text using any CLI tool without leaving the editor.

How it works

  • ! initiates the filter operator and waits for a motion
  • The motion defines which lines to filter (e.g., 5j for the next 5 lines, ip for the current paragraph, G for to the end of file)
  • After the motion, Vim drops to the command line with the range pre-filled; type your shell command and press <CR>
  • The selected lines are sent to the command via stdin and replaced with its stdout

Example

To sort the next 5 lines alphabetically:

banana
apple
cherry
date
elderberry

With the cursor on banana, press !4jsort<CR>:

apple
banana
cherry
date
elderberry

Other useful combinations:

!ipsort -u       " sort paragraph, remove duplicates
!ipcolumn -t     " align paragraph as a table
!GBase64         " base64-encode from cursor to end of file (macOS)

Tips

  • In Visual mode, press ! after a selection to filter just those lines
  • !! is a shorthand to filter only the current line
  • The range form :5,10!sort works the same way from command-line mode
  • The original lines go to the unnamed register before being replaced, so u undoes the filter

Next

How do I match a pattern only when it is preceded or followed by another pattern, without including that context in the match?