I need to replace one variable with another variable in a multiple strings. For example:
string1="One,two"
string2="three.four"
string3="five:six"
y=";"
for str in string1 string2 string3; do
x="$(echo "$str" | sed 's/[a-zA-Z]//g')" # extracting a character between letters
sed 's/$x/$y/'$str # I tried this, but it does not work at all.
echo "$str"
done
Expecting output:
One;two
three;four
five;six
In my output, nothing changes:
One,two
three.four
five:six
CodePudding user response:
You can use bash's substitution operator instead of sed. And simply replace anything that isn't a letter with $y.
#!/bin/bash
string1="One,two"
string2="three.four"
string3="five:six"
y=";"
for str in "$string1" "$string2" "$string3"; do
x=${str//[^a-zA-Z] /$y}
echo "$x"
done
Output is:
One;two
three;four
five;six
Note that your general approach wouldn't work if the input string has muliple delimiters, e.g. One,two,three. When you remove all the letters you get ,,, but that doesn't appear anywhere in the string.
CodePudding user response:
Addressing issues with OP's current code:
- referencing variables requires a leading
$, preferably a pair of{}, and (usually) double quotes (eg, to insure embedded spaces are considered as part of the variable's value) sedcan take as input a) a stream of text on stdin, b) a file, c) process substitution or d) a here-document/here-string- when building a
sedscript that includes variable refences thesedscript must be wrapped in double quotes (not single quotes)
Pulling all of this into OP's current code we get:
string1="One,two"
string2="three.four"
string3="five:six"
y=";"
for str in "${string1}" "${string2}" "${string3}"; do # proper references of the 3x "stringX" variables
x="$(echo "$str" | sed 's/[a-zA-Z]//g')"
sed "s/$x/$y/" <<< "${str}" # feeding "str" as here-string to sed; allowing variables "x/y" to be expanded in the sed script
echo "$str"
done
This generates:
One;two # generated by the 2nd sed call
One,two # generated by the echo
;hree.four # generated by the 2nd sed call
three.four # generated by the echo
five;six # generated by the 2nd sed call
five:six # generated by the echo
OK, so we're now getting some output but there are obviously some issues:
- the results of the 2nd
sedcall are being sent to stdout/terminal as opposed to being captured in a variable (presumably thestrvariable - per the follow-onecho???) - for
string2we find thatx=.which when plugged into the 2ndsedcall becomessed "s/./;/"; from here the.matches the first character it finds which in this case is the 1sttinstring2, so the output becomes;hree.four(and the.is not replaced) - dynamically building
sedscripts without knowing what's inx(andy) becomes tricky without some additional coding; instead it's typically easier to use parameter substituion to perform the replacements for us - in this particular case we can replace both
sedcalls with a single parameter substitution (which also eliminates the expensive overhead of two subprocesses for the$(echo ... | sed ...)call)
Making a few changes to OP's current code we can try:
string1="One,two"
string2="three.four"
string3="five:six"
y=";"
for str in "${string1}" "${string2}" "${string3}"; do
x="${str//[^a-zA-Z]/${y}}" # parameter substitution; replace everything *but* a letter with the contents of variable "y"
echo "${str} => ${x}" # display old and new strings
done
This generates:
One,two => One;two
three.four => three;four
five:six => five;six
