bmk
bmk

Reputation: 14147

(Gnu) sed command to change a matching part of a line

Is there a way in (Gnu) sed to replace all characters in a matching part of a string? For example I might have a list of file paths with several (arbitrary number of) paths in each line, e.g.:

/a/b/c/d/e /f/g/XXX/h/i /j/k/l/m
/n/o/p /q/r/s/t/u /v/x/x/y
/z/XXX/a/b /c/d/e/f

I would like to replace all the slashes in paths containing XXX keping all the others untouched, e.g.:

/a/b/c/d/e #f#g#XXX#h#i /j/k/l/m
/n/o/p /q/r/s/t/u /v/x/x/y
#z#XXX#a#b /c/d/e/f

Unfortunately I cannot come up with a solution. Maybe it's even impossible with sed. But I'm curious if somebody find a way to solve the problem.

Upvotes: 0

Views: 124

Answers (1)

Toby Speight
Toby Speight

Reputation: 30968

We can replace any / preceding XXX with no intervening spaces like this:

# Using extended regex syntax
s!/([^ ]*XXX)!#\1!

It's a very similar substitution for those that follow XXX.

Putting them together in a loop makes this program:

#!/bin/sed -rf

:loop
s!/([^ ]*XXX)!#\1!
s!(XXX[^ ]*)/!\1#!
tloop

Output:

/a/b/c/d/e #f#g#XXX#h#i /j/k/l/m
/n/o/p /q/r/s/t/u /v/x/x/y
#z#XXX#a#b /c/d/e/f

That said, it might be simpler to use a pipeline, to break the file paths into individual lines and then reassemble them after the substitution:

sed -e 's/ *$//;s/  */&\n/g' \
  | sed -e '/XXX/y,/,#,' \
  | sed -e ':a;/ $/{N;s/\n//;ba}'

Upvotes: 2

Related Questions