Lone Learner
Lone Learner

Reputation: 20698

Command substitution and field splitting in shell

I understand why the following command fails.

$ a=foo bar
-bash: bar: command not found

It attempts to first execute a=foo and then execute bar which fails because there is no such command called bar.

But I don't understand why this works. I was expecting the following command to fail as well.

$ a=$(echo foo bar)
$ echo "$a"
foo bar

As per http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 first command substitution happens, and then field splitting happens.

2.6 Word Expansions

This section describes the various expansions that are performed on words. Not all expansions are performed on every word, as explained in the following sections.

Tilde expansions, parameter expansions, command substitutions, arithmetic expansions, and quote removals that occur within a single word expand to a single field. It is only field splitting or pathname expansion that can create multiple fields from a single word. The single exception to this rule is the expansion of the special parameter '@' within double-quotes, as described in Special Parameters.

The order of word expansion shall be as follows:

  1. Tilde expansion (see Tilde Expansion), parameter expansion (see Parameter Expansion), command substitution (see Command Substitution), and arithmetic expansion (see Arithmetic Expansion) shall be performed, beginning to end. See item 5 in Token Recognition.

  2. Field splitting (see Field Splitting) shall be performed on the portions of the fields generated by step 1, unless IFS is null.

  3. Pathname expansion (see Pathname Expansion) shall be performed, unless set -f is in effect.

  4. Quote removal (see Quote Removal) shall always be performed last.

So after command subsitution,

a=$(echo foo bar)

becomes

a=foo bar

And then after to field splitting, a=foo should be executed first and then bar should be executed and then we should have the same error, i.e. bar: command not found. Why does a=$(echo foo bar) work fine then?

Upvotes: 4

Views: 223

Answers (1)

Etan Reisner
Etan Reisner

Reputation: 81012

The answer is in 2.9.1 Simple Commands I believe.

Specifically points 1 and 4:

 1. The words that are recognized as variable assignments or redirections according to Shell Grammar Rules are saved for processing in steps 3 and 4.

 4. Each variable assignment shall be expanded for tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal prior to assigning the value.

Or in the bash reference manual in 3.4 Shell Parameters:

A variable may be assigned to by a statement of the form

name=[value]

If value is not given, the variable is assigned the null string. All values undergo tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal (detailed below).

Upvotes: 2

Related Questions