Ever wanted to replace the text in the middle of a string based upon a pattern match? Yeah, me too.
You can define capturing groups in a sed expression which will help with the match but not get in the way of the substitution. This page from StackOverflow provides a great example of how this is done.
I wanted to update the configurations for some of the disks defined in /etc/fstab to use the noatime and nodiratime directives. The defaults setting was already in place and the new directives would be appended to the current setting. This needed to be done across 32 servers, so manual editing was not going to happen. I used the statement below to perform the update.
sed -i 's/\(^.*data.*\)defaults/\1defaults,noatime,nodiratime/' /etc/fstab
In this case, I wanted to find all lines that contained the word “data” and “defaults”. The space between the two words could be any number of characters. The portion of the statement in parentheses defines the capturing group which represented the matching pattern. The parens had to be escaped with a “\” character or an error would be returned.
The replacement pattern is defined next and it is proceeded by a 1. You can use multiple capturing groups in an expression and they are referenced numerically in their order of appearance. So if you had another capturing group following the first, you would refer to it with a 2. You must also escape the reference number or an error will occur.
When the command was executed, the data file went from this:
UUID=abcd /data/01 ext4 defaults 1 2
UUID=efgh /data/02 ext4 defaults 1 2
UUID=hijk /data/03 ext4 defaults 1 2
UUID=lmno /data/04 ext4 defaults 1 2
UUID=abcd /data/01 ext4 defaults,noatime,nodiratime 1 2
UUID=efgh /data/02 ext4 defaults,noatime,nodiratime 1 2
UUID=hijk /data/03 ext4 defaults,noatime,nodiratime 1 2
UUID=lmno /data/04 ext4 defaults,noatime,nodiratime 1 2
P.S. The UUIDs have been changed to protect the innocent