Home > Blockchain >  Way to replace one variable with another in a string
Way to replace one variable with another in a string

Time:06-23

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 the sed 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 the str variable - per the follow-on echo ???)
  • for string2 we find that x=. which when plugged into the 2nd sed call becomes sed "s/./;/"; from here the . matches the first character it finds which in this case is the 1st t in string2, so the output becomes ;hree.four (and the . is not replaced)
  • dynamically building sed scripts without knowing what's in x (and y) 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
  • Related