Differences between revisions 1 and 2
Revision 1 as of 2010-03-16 16:58:09
Size: 2867
Editor: GreyCat
Comment: first draft
Revision 2 as of 2010-03-17 19:25:18
Size: 4051
Editor: GreyCat
Comment: more stuff
Deletions are marked like this. Additions are marked like this.
Line 2: Line 2:

= Standard quoting =
Line 25: Line 27:
When in doubt, quote your parameter expansions. It's exceedingly rare that you would need one to be unquoted, and if that's the case, you'll know it. When in doubt, quote your parameter expansions. It's rare that you would need one to be unquoted, and if that's the case, you'll know it.
Line 61: Line 63:
= Bash extensions =

Bash introduces two additional forms of quoting. The first is `$'...'` which acts like single quotes except that backslash-escaped combinations are expanded as specified by the ANSI C standard. This allows a convenient way to embed nonprintable characters into strings, or to pass them as arguments.

{{{
IFS=$' \t\n'
# sets the IFS variable to the three-byte string containing
# a space, a tab, and a newline
}}}

The second form is `$"..."` and is used for [[BashFAQ/098|localization support]].

In addition to these, bash uses quotes to suppress the "specialness" of the right-hand-side of an `=` or `=~` operator inside a `[[` keyword. That sounds complicated, but it's simpler when shown as an example:

{{{
if [[ $path = foo* ]]; then
# unquoted foo* acts as a glob

if [[ $path = "foo*" ]]; then
# quoted "foo*" is a literal string

if [[ $path =~ $some_re ]]; then
# the contents of $some_re are treated as an ERE

if [[ $path =~ "$some_re" ]]; then
# the contents of $some_re are treated as a literal string
# despite the =~ operator
}}}

See [[glob]] and RegularExpression for explanations of those terms.

Quoting in shell programming is extremely important. There are multiple types of quotes, and you must know how and when to use each type.

Standard quoting

A shell command is parsed by the shell into words, using whitespace (regardless of the IFS variable) and other shell metacharacters. The first function of quoting is to permit words to contain these metacharacters.

echo '&'

Without quotes, the & would put the echo command into the background. With quotes, the & is simply made into a word, and passed as an argument to the echo command instead.

The quotes are not actually passed along to the command. They are removed by the shell. In the example above, the echo command sees only the &, not the quotes.

Single quotes (apostrophes) prevent all interpretation of the characters between them.

Double quotes permit parameter expansions and command substitutions to occur inside them. They do not allow filename expansions, brace expansions, process substitutions, tilde expansion, etc.

The second purpose of quoting is to prevent WordSplitting and globbing.

cp -- "$filename" "$destination"

In this example, the double quotes protect each parameter (variable) from undergoing word splitting or globbing should it happen to contain whitespace or wildcard characters (* or ? or [...]). Without the quotes, a filename like hot stuff.mp3 would be split into two words, and each word would be passed to the cp command as a separate argument. That is not what we want.

When in doubt, quote your parameter expansions. It's rare that you would need one to be unquoted, and if that's the case, you'll know it.

Assorted examples, to show how things should be done. Some of these examples use bash/ksh syntax that won't work in strict POSIX shells.

for file in "$@"

for element in "${array[@]}"

for index in ${!array[*]}
# We omit quotes here because the indices are a list of numbers,
# which must be word-split in order to be processed.  Numbers will
# never undergo glob expansion either, so we can skip "set -f".

find_opts=('(' -iname '*.jpg' -o -iname '*.gif' -o -iname '*.png' ')')
find . "${find_opts[@]}" -print

echo 'Don'\''t walk!'

echo "The matching line is: $(grep foo "$filename")"
# Note that the quotes inside the $() command substitution are nested.
# This looks wrong to a C programmer, but it is correct in shells.

The third type of quote is the backtick (`) or back quote. It's a deprecated markup for command substitutions, used in Bourne shells before the introduction of the $(...) syntax. For a discussion of the difference between `...` and $(...) please see BashFAQ/082.

Bash extensions

Bash introduces two additional forms of quoting. The first is $'...' which acts like single quotes except that backslash-escaped combinations are expanded as specified by the ANSI C standard. This allows a convenient way to embed nonprintable characters into strings, or to pass them as arguments.

IFS=$' \t\n'
# sets the IFS variable to the three-byte string containing
# a space, a tab, and a newline

The second form is $"..." and is used for localization support.

In addition to these, bash uses quotes to suppress the "specialness" of the right-hand-side of an = or =~ operator inside a [[ keyword. That sounds complicated, but it's simpler when shown as an example:

if [[ $path = foo* ]]; then
# unquoted foo* acts as a glob

if [[ $path = "foo*" ]]; then
# quoted "foo*" is a literal string

if [[ $path =~ $some_re ]]; then
# the contents of $some_re are treated as an ERE

if [[ $path =~ "$some_re" ]]; then
# the contents of $some_re are treated as a literal string
# despite the =~ operator

See glob and RegularExpression for explanations of those terms.


CategoryShell

Quotes (last edited 2024-03-07 22:57:49 by emanuele6)