2

When scripting in Bash, we learned to assign a variable to the output of a command, we can use the construct:

variable=$(command-string)

This is known as command substitution and executes the contents of the command string in a sub shell environment.

I may have discovered an anomaly.

When executing this form of command substitution, WITHOUT variable assignment, the results differ.

Example:

cmd=date
var=$(echo $cmd)
echo $var
$(echo $cmd)

Output:

date
Fri Jun 29 15:11:58 EDT 2018

The command substitution without variable assignment appears to be attempting an eval of stdout of command execution whereas the variable assignment does not.

  • I don't see what is unexpected. $(echo $cmd) produces the string date. Since it is in the first position in the command, the shell executes it. You will get the same result for cmd=date; var=$(echo $cmd); $var. – AlexP Jul 3 '18 at 16:19
5

Your command substitution evaluates to: date

Since you are not assigning it to anything, what you are doing is essentially just typing date at the command prompt.

$ set -x
$ cmd=date
+ cmd=date
$ var=$(echo $cmd)
++ echo date
+ var=date
$ echo $var
+ echo date
date
$ $(echo $cmd)
++ echo date
+ date
Fri Jun 29 13:26:55 MDT 2018

Since date is a valid command it executes it as expected.

-1

I believe I have come up with a reasonable, somewhat concise, technical explanation. We are dealing with a CLI (Command line interpreter) and the results of command substitution depend on the phase of interpretation when the parser encounters the substitution token "$(".

cmd="date"

Simple assignment; variable "cmd" has the string "date".

var=$(echo $cmd)
$(echo $cmd)

In the first case, the parser (which reads from left to right) encountered a token "=" so it knows it is expecting an equivalence string for a variable assignment. In the second case, the parser had not determined the type of command it was dealing with, when it hit "$(". In both cases the parsing pauses and a subshell environment is created. The string between the parentheses is interpreted by the CLI and the contents of stdout is used to replace "$(", the corresponding, unquoted right parenthesis and everything between. Now, the CLI picks up where it left off. In this example, in both instances, stdout contains the string "date". In the first instance, the CLI was expecting an equivalence string, so it interprets "var=date" as assigning the string "date" to variable "var". In the second instance, the CLI interprets "date". Since date is a valid program in the current path, that program is invoked. So, nothing is actually wrong, it's just the way the interpreter carries out the substitution.

  • 2
    It's not really even about the assignment vs. non-assignment, just that the first shell word (except for assignments) that results after the expansions are processed, is taken as the name of a command. $(echo date) will run date, but ls $(echo date) will run ls (with an arguments of date). – ilkkachu Jul 3 '18 at 16:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.