All you need is the global command:
:global/^#/.!your awk command
This says « for all lines matching ^#
, filter them through your awk command
». The .
is explicitly needed here (where it usually isn't) because :!
runs a command, but :[range]!
runs the command as a filter. While :global
usually acts like a range, in this odd case it doesn't.
Since %
is always current filename, you need to escape it as \%
. And when running !
commands, !
will be replaced by the last !
command. To avoid that, you can escape it too: \!
.
This gives
global/^#/.!awk 'BEGIN{split("a the to at in on with and but or",w); for(i in w)nocap[w[i]]}function cap(word){return toupper(substr(word,1,1)) tolower(substr(word,2))}{for(i=1;i<=NF;++i){printf "\%s\%s",(i==1||i==NF||\!(tolower($i) in nocap)?cap($i):tolower($i)),(i==NF?"\n":" ")}}'
As was pointed out in the comments, an even more compose-able/reusable way of doing this would be to create a script something like:
#! /usr/bin/awk -f
BEGIN {
split("a the to at in on with and but or",w)
for(i in w)
nocap[w[i]]
}
function cap(word) {
return toupper(substr(word,1,1)) tolower(substr(word,2))
}
{
for(i=1;i<=NF;++i) {
printf "%s%s", (i==1 || i==NF || !(tolower($i) in nocap) ? cap($i) : tolower($i)), (i==NF?"\n":" ")
}
}
If you save this on somewhere on your PATH
(call it, say, titlecase
) and chmod u+x
it, then you can call it from your shell and from vim:
:global/^#/.!titlecase
One benefit this has is you don't need the escaping at all.