I have a log file full of arbitrary lines, interspersed with some lines which are a proper xml sequence, with all the tags on a single line (for each sequence). I want to simply process this so that all the xml lines become broken out in easy to read format. There is a utility in linux called xmllint that looks useful here.
I am able to do this easily manually in vim, by searching for
!! xmllint --format --recover -
Interestingly,
:! cmd
doesn't work here, but
:.! cmd
does. I'm not sure if that's because the first one is legacy "Ex" mode, while adding the range (.) makes the second one a Vim filter?
What I want is to be able to do it automatically, not by saving manual commands in a recorded register and replaying it possibly tens or hundreds of times, but O(1) commands to simply find all the lines with "xml" and filter them through this external command, replacing their text in the buffer with the nicely formatted version.
This should definitely be possible given the power and style of vim, but I've tried for hours and can't do it.
The idea is something like
:%g/xml/normal!!:$xmllint --format --recover -
I've tried with and without normal, and all the variations of : and ! to try to filter through an external command.
Most of the time, it does absolutely nothing to the buffer, nothing even to undo, even though the :g part is definitely matching. Other times, like
:%g/xml/!xmllint --format --recover -
it waits forever until I send a Ctrl-C for each match. Basically it seems to be waiting for xmllint which is stuck waiting at STDIN.
How can I take a working :%g/pattern/ command and make it replace the matching lines with the output of an external command (a command which itself takes the aforementioned matching line as its input) ?
:h :!
and:h :range!
. – Antony Jan 5 '17 at 0:25%
andg
don't go together - did you mean:g/xml/ .! xmllint --format --recover -
? – muru Jan 5 '17 at 12:26