# Grandma's Fridge

A TitanOfOld dev blog

# Perl Conditional Replace Depending On Match

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.

There is.

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)