Parameter Expansion
显然的答案是使用参数扩展的特殊形式之一:
: ${STATE?"Need to set STATE"}
: ${DEST:?"Need to set DEST non-empty"}
或者更好(请参阅下文关于双引号位置的部分):
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
第一种变体(仅使用?
)需要设置STATE,但STATE =“”(空字符串)是可以的-不完全是您想要的,但是是替代和较旧的表示法。
第二个变体(使用:?
)要求设置并且非空的DEST。
如果您没有提供消息,系统会提供默认的消息。
${var?}
结构可移植回到 Version 7 UNIX 和 Bourne Shell(大约在1978年)。${var:?}
结构稍微新一些:我认为它是在 System III UNIX(大约在1981年)中出现的,但它可能先出现在 PWB UNIX 中。因此它存在于 Korn Shell 中,并在 POSIX shells 中,包括特别是 Bash。
它通常在 shell 的 man 页面中记录在名为 "Parameter Expansion" 的部分中。例如,bash 手册说:
${parameter:?word}
如果为Null或未设置,则显示错误。 如果参数为null或未设置,则会将单词扩展(或一条关于此单词的消息)写入标准错误流,并退出非交互式shell。否则,将替换参数的值。
The Colon Command
我应该补充一下,冒号命令只是对其参数进行求值,然后成功执行。这是原始的shell注释符号(在#到行末之前)。很长一段时间,Bourne shell脚本的第一个字符都是冒号。C Shell会读取脚本,并使用第一个字符来确定它是为C Shell(#哈希)还是Bourne shell(:冒号)而编写的。然后内核加入了支持#!/path/to/program,Bourne shell增加了#注释,冒号传统就被淘汰了。但是,如果您遇到以冒号开头的脚本,现在您将知道为什么。
Position of double quotes
在评论中,blong提出了这个问题。
对于这个讨论有什么想法?https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749
讨论的要点是:
但是,当我使用0.4.1版本的shellcheck
进行检查时,我收到了这条信息:
In script.sh line 13:
: ${FOO:?"The environment variable FOO must be set and non-empty"}
^-- SC2086: Double quote to prevent globbing and word splitting.
关于这件事,你有什么建议?
简短的回答是“按照shellcheck
所建议的去做”。
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
To illustrate why, study the following. Note that the :
command doesn t echo its arguments (but the shell does evaluate the arguments). We want to see the arguments, so the code below uses printf "%s
"
in place of :
.
$ mkdir junk
$ cd junk
$ > abc
$ > def
$ > ghi
$
$ x="*"
$ printf "%s
" ${x:?You must set x} # Careless; not recommended
abc
def
ghi
$ unset x
$ printf "%s
" ${x:?You must set x} # Careless; not recommended
bash: x: You must set x
$ printf "%s
" "${x:?You must set x}" # Careful: should be used
bash: x: You must set x
$ x="*"
$ printf "%s
" "${x:?You must set x}" # Careful: should be used
*
$ printf "%s
" ${x:?"You must set x"} # Not quite careful enough
abc
def
ghi
$ x=
$ printf "%s
" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$ unset x
$ printf "%s
" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$
请注意,在整个表达式没有双引号的情况下,$x
中的值会扩展为首先是*
,然后是文件名列表。这就是shellcheck
建议修复的内容。我没有验证它是否不接受将表达式放在双引号中的形式,但是合理的假设是可以的。