4

From the bash software manual:

${parameter/pattern/string}

The pattern is expanded to produce a pattern just as in filename expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string.
... If pattern begins with ‘%’, it must match at the end of the expanded value of parameter.

And so I've tried:

local new_name=${file/%old/new}

Where string is an absolute file path (/abc/defg/hij and old and new are variable strings.

However this seems to be trying to match the literal %sb1.

What is the syntax for this?

Expected Output:

Given

old=sb1
new=sb2

Then

/foo/sb1/foo/bar/sb1 should become /foo/sb1/foo/bar/sb2

/foo/foosb1other/foo/bar/foosb1bar should become /foo/foosb1other/foo/bar/foosb2bar

Jordan Mackie
  • 2,264
  • 4
  • 25
  • 45
  • @anubhava quickly changed the requirements there as I realized what I really needed, though it would be useful for it to work with literals too. – Jordan Mackie Jun 26 '18 at 14:45

1 Answers1

3

Using only shell-builtin parameter expansion:

src=sb1; dest=sb2
old=/foo/foosb1other/foo/bar/foosb1bar

if [[ $old = *"$src"* ]]; then
  prefix=${old%"$src"*}                  # Extract content before the last instance
  suffix=${old#"$prefix"}                # Extract content *after* our prefix
  new=${prefix}${suffix/"$src"/"$dest"}  # Append unmodified prefix w/ suffix w/ replacement
else
  new=$old
fi

declare -p new >&2

...properly emits:

declare -- new="/foo/foosb1other/foo/bar/foosb2bar"
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441