Given a string such as
string="val1 val2 val3 val4"
how can you use bash substring replacement to remove a given substring and its adjoining space (which may or may not be present)?
For example, this results in extra spaces:
val='val2'
string=${string/$val/}
# string = "val1 val3 val4"
In my real-life code, I won't know in advance what the substring is or where it resides in the string, so it will be unknown if it has leading or trailing spaces. I wanted to do something like this, like you'd do in sed
, but of course it didn't work:
val=" *val2 *"
string=${string/$val/ }
# In my fictitious universe, string = "val1 val3 val4"
# In the real world, string = "val1"
In sed
, I would use something like sed -e 's/ *val2 */ /'
, but I'd like to do all this from within bash.
Is there a way to define the substring such that the pattern contains zero-or-more spaces + 'val2' + zero-or-more spaces?
Consider as an initial state:
v=val2
string="val1 val21 val2 val3 val4"
Implementing the precise behavior this question asks for will result in:
string="val1 1 val3 val4"
...or, perhaps:
string="val1 1 val2 val3 val4"
I'm assuming in the below that what you really want as output in this case is:
string="val1 val21 val3 val4"
This is more involved than strictly necessary (I would use the alternate approach shown below this for the immediate case at hand), but shows use of regexes for string replacement in native bash -- which can often be a useful technique.
Consider using [[ $string =~ $re ]]
, which populates the array BASH_REMATCH
with any groups from the regex re
:
string="val1 val2 val3 val4"
val=val2
if [[ $string =~ (.*(^|[[:space:]]))"$val"(($|[[:space:]]).*) ]]; then
string="${BASH_REMATCH[1]}${BASH_REMATCH[3]}"
string=${string// / } # deal with any places where spaces are doubled up
fi
Unconditionally prepending and suffixing your string with spaces means you can use identical replacement logic, with no regex-like conditionals, with your values to be removed located anywhere in the string:
string="val1 val2 val3 val4"
val=val2
s=" $string " # Unconditionally add leading and trailing spaces
s=${s// $val / } # Substitute the value only when surrounded by space
s=${s# }; s=${s% } # Trim leading and trailing spaces back off
string=$s