Bruce Barnett 的 UNIX Shell 引用教程太棒了,还有 BashFAQ/pitfalls/分词文章中有大量有用的提示。简短摘要:
Unquoted字符串可以包含大多数字符,但不是所有字符(如换行符),并且其中许多字符(包括空格)必须进行转义。只是不要使用它们 - 如果您受到诱惑,您可能会发现修改脚本的人忘记在必要时包含引号。
单引号字符串可以包含大多数字符,包括 NUL 和换行符,但不能包含单引号,因此它们也仅适用于简单值。
反引号用于命令。仅当您的 shell 不支持时才应使用它们$()
。例子:
current_dir=`pwd` # BAD! Don't do this!
该命令很糟糕,因为当赋值的右侧未加引号时,shell 会执行分词在上面。它通常会导致难以重现的错误,因为空格很难目视检查。到引用命令 you have to use 双引号:
current_dir="$(pwd)" # OK, but loses newlines at EOF
EOF 处的换行符尤其棘手。您可以添加单个字符并将其删除,例如
# Works for some commands, but not pwd
current_dirx="$(pwd; echo x)"
current_dir="${current_dirx%x}"
printf %s "$current_dir"
,但是还有一个额外的困难,因为有些命令(例如pwd
) 将在输出末尾添加换行符anyway,所以你可能还需要删除它:
# Works for some commands, including pwd
current_dirx="$(pwd; echo x)"
current_dir="${current_dirx%$'\nx'}"
printf %s "$current_dir"
双引号可以包含any字符(尝试echo -ne "\0" | wc -c
),但请注意变量不能包含 NUL 字符。
ANSI-C 引用可以包含任何字符除 NUL 外 (Try echo -ne $'\0' | wc -c
),并提供方便的转义码,以便更轻松地使用特殊字符:
printf %s $'--$`!*@\a\b\E\f\r\t\v\\\'"\360\240\202\211 \n'
printf %q $'--$`!*@\a\b\E\f\r\t\v\\\'"\360\240\202\211 \n'
touch -- $'--$`!*@\a\b\E\f\r\t\v\\\'"\360\240\202\211 \n'
rm -- $'--$`!*@\a\b\E\f\r\t\v\\\'"\360\240\202\211 \n'