Adventures in Regular Expressions
By Chris W Beal on Oct 25, 2011
I'm one of those people who will get stuck in and solve problems, even if I don't know everything about an area a problem lies in. As such I often find I'm learning new and unexpected things. Hey, that's why I love coming to work.
So the project I'm working on at the moment relates to how we build the SRUs (the Support Repository Updates), which replace patches in Solaris 11. As such I'm learning a lot about IPS - the Image Packaging System, and in particular how the tools it provides help you deliver consistent and upgradeable packages.
The trick I picked up this week is about Regular Expressions. I have need to change some values in an FMRI of a package. I had been doing it in a set of shell scripts until Mark Nelson of the SMF team pointed out I was rewriting pkgmogrify(1)
So reading the pkgmogrify(1) man page left me feeling less than knowledgeable, I'd sort of gathered it worked with regular expressions. Now these are well known in the industry, just I've never needed to use them.
So after a bit of experimenting I find I can substitute values in a string using the "edit" directive. This is the relevant portion of the man page, which makes sense now I know the answer
edit Modifies an attribute of the action. Three arguments are taken. The first is the name of the attribute, the second is a regular expression matching the attribute value, and the third is the replacement string substituted for the portion of the value matched by the regular expression. Unlike the regular expression used to match an action, this expression is unanchored. Normal regular expression backreferences, of the form '\1', '\2', etc., are available in the replacement string, if there are groups defined in the regular expression.
The last sentence is the clincher for what I need to do. I can search a string for a pattern, and load it in to the "groups", and then reference them in the replacement string. So for example if I want to change the package version string from "-0.175.0.0.0" to "-0.175.1.1.1", I can do it using a transform, but where 175 might change and I want that to be reflected in the resulting manifest
$ cat trans/mytransform <transform set name=pkg.fmri -> edit value \
The "Groups" are defined in the round brackets eg. ([0-9]) for example. Then I can simply run pkgmogrify to get the result
$ pkgmogrify -I trans -O <output file> <input manifest> mytransform
This performs the substitution just as I needed it to.