So, as I write patches for various awful build systems, one of the things I try to do is slim down the patch file and make it easier to read. Changing “foobar-1.orig” to just a and “foobar-1” to just b makes a difference. Rather than manually edit the patch file, I turn to my dear friend, the regex search-and-replace. But, it gets to be a bit tiring editing essentially the same regex twice to get nearly identical results.
Take for example this little snippet of a real patch:
diff -Naurw pgpool-II-3.2.0.orig/pgpool.conf.sample pgpool-II-3.2.0/pgpool.conf.sample --- pgpool-II-3.2.0.orig/pgpool.conf.sample 2012-07-19 03:06:21.000000000 -0400 +++ pgpool-II-3.2.0/pgpool.conf.sample 2012-08-14 07:33:39.200695855 -0400 @@ -31,10 +31,8 @@ port = 9999 # Port number # (change requires restart) -socket_dir = '/tmp' +socket_dir = '@PGSQL_SOCKETDIR@' # Unix domain socket path # (change requires restart)
Now, I’d like to have a line that doesn’t wrap, and I’d like to save a few bytes of precious disk space, by changing the “pgpool-II-3.2.0.orig” and “pgpool-II-3.2.0” bits into a shorter “a” and “b”, respectively.
Previously, I’ve used sed, but I would run it twice. That’s a pain. I have to make sure I run the sed commands in the right order so I don’t shoot myself in the foot and have to go back to running diff again to produce the patch.
There must be a better way.
Perl’s “easy things easy and hard things possible” attitude allowed me to arrive at a short one-liner that allows me accomplish the task:
perl -pi -e 's/pgpool-II-3\.2\.0(\.orig)?/$1?a:b/eg' run_paths.patch
The secret is in the /e modifier. /e evaluates the replacement portion of the search-and-replace expression. So, the match/search portion looks for “pgpool-II-3.2.0” and if it has “.orig” it captures that and stores it into $1. The replacement portion evaluates $1. If it is a true value — not undef, an empty string, or 0 — the replacement string is a, otherwise it is b.
This one-liner handily transforms the above patch into a logically identical, more aesthetically pleasing, lighter-weight version.
diff -Naurw a/pgpool.conf.sample b/pgpool.conf.sample --- a/pgpool.conf.sample 2012-07-19 03:06:21.000000000 -0400 +++ b/pgpool.conf.sample 2012-08-14 07:33:39.200695855 -0400 @@ -31,10 +31,8 @@ port = 9999 # Port number # (change requires restart) -socket_dir = '/tmp' +socket_dir = '@PGSQL_SOCKETDIR@' # Unix domain socket path # (change requires restart)