Shell Quoting. Was: Shell tips and tricks
Ben Scott
dragonhawk at gmail.com
Mon Oct 8 10:12:11 EDT 2007
On 10/8/07, Steven W. Orr <steveo at syslang.net> wrote:
> echo $foo # Also none needed if you *know* that foo has
> # non-null value
Might be worth going into this in a bit more detail:
Shell quoting is mostly about how arguments are passed to
programs[1]. By default, the shell splits every command line into
arguments at whitespace. Quoting simply turns what would otherwise be
split into multiple arguments into one argument. The shell removes
the quotes before it passes the argument to the next level.
Quoting is only important on shell command lines (i.e., what us
humans type). Once the command line is parsed, it gets turned into an
argument list, and is stored as a series of NUL-terminated strings,
and spaces don't matter.
Single quotes (') also turn off most of things you can do with
"funny characters" (like $), making it useful for when you want a
literal string, exactly as typed, without the shell getting in the
way.
When dealing with arguments passed *to* a shell script, the
constructs $* and $@ both expand into the list of all arguments. The
difference is in how they behave when quoted. "$*" expands all
external arguments into a single argument, while "$@" expands each
external argument into separate arguments. In other words, if I
invoke a shell script "foo" as follows:
foo ding dong "dang dung"
then inside the script, "$*" would expand to:
"ding dong dang dung"
while "$@" would expand to:
"ding" "dong" "dang dung"
(quotes added for clarity; again, once arguments are parsed, quoting
is irrelevant).
> Use none when it's not needed. Use single when no interpolation is
> required. Only use double quotes when needed.
I do sometimes quote variables (myprog "$like" "$this"), even when I
"know" the quotes will not be needed. It's a defensive measure. If
the assumptions about the contents of the variables change, I don't
have to search my program for all the places where they get used.
It can also make debugging a great deal easier, especially for cases
where a variable somehow is unset when used. Say I have a command like
this:
foo --two "$DING" "$DONG" --one "$DANG"
If, for whatever reason, "$DONG" is undefined, then foo will be passed
an empty argument there. Without the quotes, something else will get
used as the second argument to "--two" (sometimes "--one", sometimes
"$DANG" with --one getting no argument), which usually results in
really confusing error messages.
Another tip about shell quoting: Prefer $( ... ) to `...`. Both
run a command and capture the output as an argument, but $( ... )
nests automatically, while `...` can create nested quoting nightmares.
> (BTW, I can be really exciting at parties.)
I suspect you're in good company here. :)
Footnotes
---------
[1] For purposes of this discussion, "programs" include shell builtins.
-- Ben
More information about the gnhlug-discuss
mailing list