regexsedpathidempotent

How to prepend a PREFIX to paths only once (in an idempotent way) in `sed` (e.g., no PREFIXPREFIX)?


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
    

    RegEx Demo

    Details: