Bruce Barnett's UNIX Shell Quote Tutorial 很棒,Bash FAQ/pitfalls/word splitting 文章有大量有用的提示。一个简短的总结:
不带引号的 字符串可以包含大多数字符,但不是所有字符(如换行符),其中许多字符(包括空格)必须被转义。只是不要使用它们 - 如果您中了这个诱惑,您可能会发现修改脚本的人在必要时忘记包含引号。
单引号字符串可以包含大多数字符,包括 NUL 和换行符,但不能包含单引号,因此它们也仅对简单值有用。
反引号用于命令。仅当您的 shell 不支持 $() 时才应使用它们。示例:
current_dir=`pwd` # BAD! Don't do this!
那个命令不好,因为当赋值的右边没有被引用时,shell 会在它上面执行word splitting。它通常会导致难以重现的错误,因为空格很难目视检查。要引用命令,您必须使用双引号:
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"
双引号可以包含任何字符(试试echo -ne "\0" | wc -c),但请注意变量不能包含NUL字符。
ANSI-C quotes 可以包含任何字符NUL 除外(试试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'