This appendix contains historical footnotes extracted from elsewhere in the document to improve readability. They appear in this appendix because although they may be of some interest, they are not critical to a general understanding of the subject.
In some early Bourne-compatible shells, the second statement below does not do what you might initially suspect:
STRING1="This is a test" |
STRING2=$STRING1 |
Most modern Bourne shells parse the right side of the assignment statement first (including any splitting on spaces), then expand the variable $STRING1
, thus copying the complete value of STRING1
into STRING2
.
Note: This pre-splitting behavior is specific to the right side of assignment statements. All other statements are split after variables are expanded.
Some older shells, however, may do the space splitting after expanding the variable. Such shells interpret the second statement as though you had typed the following:
STRING2=This is a test |
as a two-part statement: an assignment statement (FIRST_ARGUMENT=This
) followed by a command (is
) with two arguments (a
and test
).
Because there is no semicolon between the assignment and the command, the shell treats this assignment statement as an attempt to modify the environment passed to the is
command (a technique described in “Overriding Environment Variables for Child Processes (Bourne Shell)”). This is clearly not what you intended to do.
For maximum compatibility, you should always write such assignment statements like this:
STRING1="This is a test" |
STRING2="$STRING1" |
In any Bourne shell, this is interpreted correctly as:
STRING2="This is a test" |
Compatibility Note: This behavior was first introduced by zsh
because this was a common programmer mistake that caused errors.
When run as /bin/sh
, some early versions of zsh
emulate the previous Bourne shell behavior for compatibility. Thus, in a script that starts with #!/bin/sh
, the statement may fail if sh
is really zsh
.
Current versions of zsh
obey the modern splitting rules even when run as /bin/sh
.
Similarly, in modern shells, quotation marks and other special characters are parsed before expansion. Thus, quotation marks inside a variable do not affect the splitting behavior. For example:
FOO="\"this is\" a test" |
ls $FOO |
is equivalent to:
ls \"this |
ls is\" |
ls a |
ls test |
In older Bourne shells, however, this may be misinterpreted as:
ls "this is" |
ls a |
ls test |
In general, it is not worth the effort to support shells with this broken splitting behavior, and it is unlikely that you will encounter them; the modern splitting behavior has been common since the mid-1990s.
Last updated: 2010-06-18