5

From my code below, how to make the value of 'zz' become 500 after replacing 'critical_' with x on variable 'yy'

xab123=500

yy="critical_ab123"
zz=${"${yy//critical_/x}"}

echo $zz

instead the result, there is an error:

line 8: ${"${yy//critical_/x}"}: bad substitution

thanks adi

adiwhy
  • 67
  • 1
  • 1
  • 6

2 Answers2

8

May be like this:

xab123=500
yy="critical_ab123"
zz="${yy//critical_/x}"
echo ${!zz}
500
anubhava
  • 761,203
  • 64
  • 569
  • 643
1

An interesting usage is when you call a bash function, you can use indirection on the parameters passed in. Then, you can nest calls to your indirection function in a nested manner using command substitution.

deref() { echo "${!1}"; }

aa="bb"
bb="cc"
cc="hello"

echo "$(deref aa)" # bb
echo "$(deref "$(deref aa)")" # cc
echo "$(deref "$(deref "$(deref aa)")")" # hello

Here's deref used to solve the OP's problem:

deref() { echo "${!1}"; }

xab123="500"
yy="critical_ab123"
zz="$(deref "${yy//critical_/x}")"

echo "$zz" # Outputs: 500

Applied edits based on @charles-duffy comments:

  1. Disclaimer: reader beware, there are performance impacts to the command substitution used in this approach (FIFO creation, fork() of a subshell, read() and wait().
  2. Quotes were added to protect against lossy expansion, i.e. echo "$zz" is better than echo $zz
  3. Use POSIX-compliant function declaration syntax, i.e. replaced function deref { echo "${!1}" ; } with deref() { echo "${!1}" ; }
  4. Corrected quoting issue for each quoting context
Stephen Quan
  • 21,481
  • 4
  • 88
  • 75
  • 1
    Boo, hiss: Command substitution is unnecessary and has a significant performance impact (requires FIFO creation, `fork()` of a subshell, `read()` and `wait()` for same), lack of quoting makes this lossy (`echo $zz` will replace a `*` with a list of files in the current directory), and the non-standard function declaration syntax has absolutely no benefit over the POSIX-compliant alternative. – Charles Duffy Nov 20 '17 at 20:56
  • @charles-duffy I understood your feedback. I contemplated deleting this answer, but, I decided to attempt to improve it instead. I believe I comprehended your points correctly, except, I failed to understand the non-standard function declaration. Can you supply a reference? – Stephen Quan Nov 21 '17 at 00:53
  • 1
    See the relevant standards document at http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_05 -- a standards-compliant definition would be `deref() { echo "${!1}"; }`, with no `function` keyword preceding. – Charles Duffy Nov 21 '17 at 00:55
  • 1
    BTW, correct quoting (to ensure that we pass our result of modifying `yy` as a single argument, regardless of the presence of spaces or the value of IFS) would be `zz="$(deref "${yy//critical_/x}")"` -- each command substitution with `$()` starts a new quoting context. That way invocation with `yy='hello world'` would properly cause an error, instead of dereff'ing the variable named `hello` and silently ignoring the `world`. – Charles Duffy Nov 21 '17 at 00:57
  • 1
    (similarly: `"$(deref "$(deref "$(deref aa)")")"`) – Charles Duffy Nov 21 '17 at 01:25