Today a coworker posed an interesting question to me.

Given a BIG-IP configuration file with thousands of records like this…

gtm pool /Common/p_example {
    members {
        /Common/2001:668:fc78:0:f811:3ef2:fed7:98cc:vs6_2001_668_fc78_0_f811-3ef2-fed7_98cc-80 {
            order 0
        }
    }
    monitor /Common/gateway_icmp
}

…how can we easily replace every colon in the name : with \\:?

In short, /Common/2001:668:fc78:0:f811:3ef2:fed7:98cc:vs6_2001_668_fc78_0_f811-3ef2-fed7_98cc-80 needed to become /Common/2001\\:668\\:fc78\\:0\\:f811\\:3ef2\\:fed7\\:98cc\\:vs6_2001_668_fc78_0_f811-3ef2-fed7_98cc-80.

This must only be done on the lines with start with /Common and which also contain the string vs6. He could not guarantee that colons would not be found elsewhere in the file.

This required some Googling on my part before I realized that sed has this ability natively. In short, you can specify a regular expression or string which must be matched before sed will perform any substitutions.

Here’s what I came up with: sed '/\/Common.*vs6/s/:/\\\\:/g'

[18:24] james_simas@widget ~/Downloads $ cat example_file.txt
gtm pool /Common/p_example {
    members {
        /Common/2001:668:fc78:0:f811:3ef2:fed7:98cc:vs6_2001_668_fc78_0_f811-3ef2-fed7_98cc-80 {
            order 0
        }
    }
    monitor /Common/gateway_icmp
}
[18:24] james_simas@widget ~/Downloads $ cat example_file.txt | sed '/\/Common.*vs6/s/:/\\\\:/g'
gtm pool /Common/p_example {
    members {
        /Common/2001\\:668\\:fc78\\:0\\:f811\\:3ef2\\:fed7\\:98cc\\:vs6_2001_668_fc78_0_f811-3ef2-fed7_98cc-80 {
            order 0
        }
    }
    monitor /Common/gateway_icmp
}
[18:24] james_simas@widget ~/Downloads $