I have a file with a complex multi-line command and some unrelated text. I need to prepend certain paths (for example, /foo) with a prefix /bar. The script may ran more than once, but must not prepend multiple /bar prefixes to the same path. For example, run the script once to get /bar/foo, run it again, and still get /bar/foo, not /bar/bar/foo. I must use sed for consistency with the existing code base.
I came up with the desired result (below), but my method seems cumbersome. Is there a better (shorter, less repetitive) way?
$ echo '/foo' > infile
$ cat infile
"/foo" /foo
# Replace once, change expected:
$ sed -i '\#bar/foo#!s#\(/foo\)#/bar\1#g' infile
$ cat infile
"/bar/foo" /bar/foo
# Replace twice - no change expected:
$ sed -i '\#bar/foo#!s#\(/foo\)#/bar\1#g' infile
$ cat infile
"/bar/foo" /bar/foo
EDIT: Do not use my "solution": it is wrong in an important edge case, see the comments below
>Solution :
You may use this sed solution with an optional group to replace /foo with /bar/foo but skip matching when /bar is already there:
sed -E 's~(/bar)?(/foo)~/bar\2~g' file
Details:
(/bar)?: Match optional/barin capture group #1(/foo): Match/fooin capture group #2/bar\2: Replacement to always put/barfollowed by value we captured in capture group #2