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) sed
can 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
sed
script that includes variable refences thesed
script 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
sed
call are being sent to stdout/terminal as opposed to being captured in a variable (presumably thestr
variable - per the follow-onecho
???) - for
string2
we find thatx=.
which when plugged into the 2ndsed
call becomessed "s/./;/"
; from here the.
matches the first character it finds which in this case is the 1stt
instring2
, so the output becomes;hree.four
(and the.
is not replaced) - dynamically building
sed
scripts 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
sed
calls 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