Replace a regular expression within vim with an output produced by a console command with the expression as its argument?
let's say I have a file with the following content:
This is a _file_ which has some _special_ keywords, that I would _like_ to replace.
I can do a search and replace of the speical keywords with "%s/_*_/something", but I would like "something" to be an output of an external command. Is this possible in vim, or do I need to awk it?
Solution 1:
Yes, you can. See :help sub-replace-special
; the \=
allows you to replace with a Vim expression. And system()
can execute an external command and return its output. See my trivial example with hostname
. Note that I had to use substitute()
to get rid of the trailing newline character(s) in the output.
:%s/_[^_]*_/\=substitute(system('hostname'),'\n','','g')/g
PS: I also corrected your regexp pattern to match your example.
Solution 2:
In Ingos answer, which helped me a lot, I don't see how to reference a subpattern of the match and use it as an argument to the shell command ("produced by a console command with the expression as its argument").
In my case I had log lines of the following form: [<unix timestamp>] <message>
, i.e. [1406844000] foobar
. I wanted to prepend them with the time in a human readable form.
The following vim command matches the timestamp (submatch 1) and the message (the rest, submatch 2) and prepends the time string from date command:
:% s/^\[\(\d\+\)\] \(.*\)$/\=substitute(system('date -d @'.submatch(1)),'\n', '', 'g').': ['.submatch(1).'] '.submatch(2)/
[1406844000] foobar
gets Fr 1. Aug 00:00:00 CEST 2014: [1406844000] foobar
.
HTH