3

Can someone explain why A and B behave differently?

A=`echo hello how are you | wc -w`

and

CMD="echo hello how are you | wc -w"
B=`$CMD`

They give different results:

$echo $A
4

$echo $B
hello how are you | wc -w

What I would like to have is a command in a variable that I can execute at several points of a script and get different values to compare. It used to work fine but if the command has a pipe, it doesn't work.

Cyrus
  • 84,225
  • 14
  • 89
  • 153
Martin Massera
  • 1,718
  • 1
  • 21
  • 47
  • 4
    Storing shell syntax (like pipes, quotes, etc) in variables doesn't work. Variables are for data, not executable code. If you want to store executable code, use a function, that's what they're for. See [BashFAQ #50: "I'm trying to put a command in a variable, but the complex cases always fail!"](http://mywiki.wooledge.org/BashFAQ/050) and many previous questions about this (but avoid all suggestions involving `eval` -- it is a huge bug magnet). – Gordon Davisson Sep 17 '22 at 21:58

1 Answers1

4
  • `` (i.e. backticks) or $() in bash referred as command substitution.
  • "" - used e.g. to preserves the literal value of characters, i.e. data.
  1. In the your first example, the command echo hello how are you | wc -w is executed and its value 4 assigned to A, hence you get 4.

  2. In your second example it an assignment of a string to a variable B and by `$CMD` the | is not "evaluated" because of late word splitting (see here for further information), and you get hello how are you | wc -w.

What you need can be done with eval command as follows:

CMD="echo hello how are you | wc -w"
echo `eval $CMD`            # or just eval "$CMD"
# Output is 4
m19v
  • 1,800
  • 4
  • 11
  • 26
  • 2
    _an assignment of a string to a variable B and by `$CMD` its value is not "evaluated"_ --> if that were the case, then `B` would equal "echo hello how are you | wc -w" but it doesn't: it equals "hello how are you | wc -w". So the `echo` command _was_ executed. It just didn't pipe into `wc`. – k314159 Sep 18 '22 at 14:09
  • 1
    @k314159 adjusted my answer. – m19v Sep 18 '22 at 14:12
  • I still don't understand what is the logic behind running the echo but not the pipe... But thanks for giving the eval solution! – Martin Massera Sep 19 '22 at 04:25
  • 1
    @MartinMassera Because of 'late word splitting' the pipe it not evaluated, see https://unix.stackexchange.com/a/388352/393118 for further information. I add the link to my answer as well. – m19v Sep 19 '22 at 17:58
  • 1
    It's important to use quotes -- `eval "$CMD"`, not `eval $CMD`. Otherwise you can get filenames injected into code if your string word-splits to include any globs. – Charles Duffy Nov 04 '22 at 01:43