Jay Taylor's notes

back to listing index

Replace Last Occurrence of Substring in String (bash)

[web search]
Original source (stackoverflow.com)
Tags: bash command-line shell-scripting string-manipulation stackoverflow.com
Clipped on: 2019-04-25

2

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

asked Jun 26 '18 at 14:33
@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
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"
answered Jun 26 '18 at 14:47
Image (Asset 2/2) alt=
Works perfectly thank you! – Jordan Mackie Jun 26 '18 at 14:58

Your Answer

community wiki

Not the answer you're looking for? Browse other questions tagged or ask your own question.

asked

10 months ago

viewed

497 times

active

10 months ago