Bruce Barnett 的 UNIX Shell 引用教程很棒,Bash常见问题解答/陷阱/分词文章有大量有用的提示。一个简短的总结:
未加引号的字符串可以包含大多数字符,但不是所有字符(如换行符),其中许多字符(包括空格)必须被转义。只是不要使用它们——如果你中了这个诱惑,你可能会发现修改脚本的人在必要时忘记了包含引号。
单引号字符串可以包含大多数字符,包括 NUL 和换行符,但不能包含单引号,因此它们也仅对简单值有用。
反引号用于命令。仅当您的 shell 不支持时才应使用它们$()
。例子:
current_dir=`pwd` # BAD! Don't do this!
该命令很糟糕,因为当未引用赋值的右侧时,shell 会对其进行分词。它通常会导致难以重现的错误,因为空格很难目视检查。要引用命令,您必须使用双引号:
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
都会在其输出末尾添加换行符,因此您可能还必须删除它:
# Works for some commands, including pwd
current_dirx="$(pwd; echo x)"
current_dir="${current_dirx%$'\nx'}"
printf %s "$current_dir"
双引号可以包含任何字符 (Try echo -ne "\0" | wc -c
),但请注意变量不能包含 NUL 字符。
ANSI-C 引号可以包含除 NUL (Tryecho -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'