Replace a string based on input

I am trying to read a value from a mapping file and would need to replace the value based on country parameter

source_table_@ctry_final
Expected
final_var=source_table_aus_final
If the country is in nz,usa,uk then 
final_var=diff_table_nz_final
final_var=diff_table_usa_final
like that

else
final_var=source_table_aus_final

My try


final_var=$(echo "source_table_@ctry_final"| sed -e "s/\@ctry/${ctry_input}/")

Please state the operating system, including version, and the shell you are using.

This works in ksh93 (Version AJM 93u+ 2012-08-01) on Ubuntu 18.04.3 LTS:

$ src=source_table_@ctry_final
$ rplst=nz,usa,uk
$ echo ${src/@ctry/{$rplst}}
source_table_nz_final source_table_usa_final source_table_uk_final

Strangely enough, it doesn't work with bash (4.4.20(1)-release):

$ echo ${src/ctry/{$rplst}}
source_table_{nz,usa,uk_final}

If anybody knows why, could we start a new thread on this, uh, feature?
[..]

In bash , the unloved, deprecated eval helps:

eval echo ${src/@ctry/{$rplst\}}
 source_table_nz_final source_table_usa_final source_table_uk_final

and, no, the $ and { need to be in that sequence in order to make it a "brace expansion", which, in turn, can only be recognized / evaluated by the evil eval .

1 Like

But expected would be below. source string needs to be replaced with diff

diff_table_usa_final

Shell is bash

How is that "country parameter" supplied and evaluated?

The @ctry part has which value, for _aus_ to be part of the final string?

Which table is relevant - diff_table or source_table - or is the distinction part of the problem?

What is and which value has ctry_input ? Where does it come into play?

It is because of the parsing order of the shell. In bash brace expansions are performed before any of the other expansions, hence the need for eval (usual caution applies (security)!) for a second round of expansions after the first round.

Unlike bash, ksh93 seems to do variable expansion before brace expansion. (Scrutinizer just said it.)

Master_Mind, I am not fully getting your requirement, but here is how you can adjust the ctry_input variable

#!/bin/sh
ctry_input=$1
case $ctry_input in
nz|usa|uk)
;;
*)
  ctry_input=aus
;;
esac
sed "s/@ctry/$ctry_input/"

This sample script you can run with a "uk" or "usa" argument, for example

sh sample.sh uk < inputfile

--- Post updated at 12:39 ---

To meet your sourc/diff replacement requirement, you can move the sed into the case-branch:

#!/bin/sh
ctry_input=$1
case $ctry_input in
nz|usa|uk)
  sed "s/@ctry/$ctry_input/
  s/source_table/diff_table/"
;;
*)
  ctry_input=aus
  sed "s/@ctry/$ctry_input/"
;;
esac

Not sure (as your requirement is still unclear) if this one, using recent bash 's extglob option and some "parameter expansions", gets you somewhere:

shopt -s extglob
rplst="nz|usa|uk"
for ctry in de nz usa uk aus aut nl
  do    VLD=${ctry/${ctry/@($rplst)}} 
        SD=${VLD:+diff}
        final_var=${SD:-source}_table_${VLD:-aus}_final
        echo $final_var
done
source_table_aus_final
diff_table_nz_final
diff_table_usa_final
diff_table_uk_final
source_table_aus_final
source_table_aus_final
source_table_aus_final

Let me be clear once again as per below code, i am getting ctry_input as input to my shell program. Where in if i get countries like nz,usa,uk then source should be replaced as diff

diff_table_nz_final

Apart from nz,usa,uk it should be

source_table_<any_other_country>_final

any_other_country if eg if i pass as aus then it would source_table_aus_final

final_var=$(echo "source_table_@ctry_final"| sed -e "s/\@ctry/${ctry_input}/")

Basically would need to tweak the above code

for ctry in de nz usa uk aus aut nl
  do    VLD=${ctry/${ctry/@($rplst)}} 
        SD=${VLD:+diff}
        final_var=${SD:-source}_table_${ctry}_final
        echo $final_var
done
source_table_de_final
diff_table_nz_final
diff_table_usa_final
diff_table_uk_final
source_table_aus_final
source_table_aut_final
source_table_nl_final

Thanks RudiC for your help. But is there a way to tweak the existing code itself

final_var=$(echo "source_table_@ctry_final"| sed -e "s/\@ctry/${ctry_input}/")

why i am saying is because you if i give other than in that case only ctry only needs to be replaced

echo "other_table_@ctry_final"

I am trying to achieve madeingermany's method

final_var=$(echo "source_table_@ctry_final" | case $ctry_input in nz|usa|uk) sed "s/@ctry/$ctry_input/s/source_table/diff_table/";;*) sed "s/@ctry/$ctry_input/" ;; esac )