Search code examples
stringbashshelleval

bash: Implicit string evaluation


In bash, I can evaluate a string as a statement, e.g.

a="echo hello"
eval $a

I recently found that you can also just expand a using

$a

and it seems to work just as well.

Multi-line input does not work, but other than that, is $a generally a legal substitution for eval $a?


Solution

  • No. First of all, you want to do eval "$a", or what you evaluate could run away from you. But more than that, $a will not do any expansions:

    a='echo {a,b}{c,d}'
    $a
    # => {a,b}{c,d}
    eval `$a`
    # => ac ad bc bd
    
    a='echo ~'
    $a
    # => ~
    eval "$a"
    # => /home/amadan
    
    foo=bar
    a='echo $foo'
    $a
    # => $foo
    eval "$a"
    # => bar
    
    a='echo $(which echo)'
    $a
    # => $(which echo)
    eval "$a"
    # => /usr/bin/echo
    
    a='echo $((1+2))'
    $a
    # => $((1+2))
    eval "$a"
    # => 3
    
    a='sort <(echo foo; echo bar)'
    $a
    # => sort: cannot read: <(echo: No such file or directory
    eval "$a"
    # => bar
    # => foo
    
    a='echo *'
    $a
    # => echo *.txt
    eval "$a"
    # => first.txt second.txt
    

    You can use eval to assign variables:

    a='baz=quux'
    $a
    # => -bash: baz=quux: command not found
    eval "$a"
    # no output
    echo "$baz"
    # => quux
    

    There may be more that I did not think of.