Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
606 views
in Technique[技术] by (71.8m points)

linux - What's the point of eval/bash -c as opposed to just evaluating a variable?

Suppose you have the following command stored in a variable:

COMMAND='echo hello'

What's the difference between

$ eval "$COMMAND"
hello

$ bash -c "$COMMAND"
hello

$ $COMMAND
hello

? Why is the last version almost never used if it is shorter and (as far as I can see) does exactly the same thing?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The third form is not at all like the other two -- but to understand why, we need to go into the order of operations when bash in interpreting a command, and look at which of those are followed when each method is in use.

Bash Parsing Stages

  1. Quote Processing
  2. Splitting Into Commands
  3. Special Operator Parsing
  4. Expansions
  5. Word Splitting
  6. Globbing
  7. Execution

Using eval "$string"

eval "$string" follows all the above steps starting from #1. Thus:

  • Literal quotes within the string become syntactic quotes
  • Special operators such as >() are processed
  • Expansions such as $foo are honored
  • Results of those expansions are split on characters into whitespace into separate words
  • Those words are expanded as globs if they parse as same and have available matches, and finally the command is executed.

Using sh -c "$string"

...performs the same as eval does, but in a new shell launched as a separate process; thus, changes to variable state, current directory, etc. will expire when this new process exits. (Note, too, that that new shell may be a different interpreter supporting a different language; ie. sh -c "foo" will not support the same syntax that bash, ksh, zsh, etc. do).


Using $string

...starts at step 5, "Word Splitting".

What does this mean?

Quotes are not honored.

printf '%s ' "two words" will thus parse as printf %s "two words", as opposed to the usual/expected behavior of printf %s two words (with the quotes being consumed by the shell).

Splitting into multiple commands (on ;s, &s, or similar) does not take place.

Thus:

s='echo foo && echo bar'
$s

...will emit the following output:

foo && echo bar

...instead of the following, which would otherwise be expected:

foo
bar

Special operators and expansions are not honored.

No $(foo), no $foo, no <(foo), etc.

Redirections are not honored.

>foo or 2>&1 is just another word created by string-splitting, rather than a shell directive.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...