参数扩展
显而易见的答案是使用参数扩展的一种特殊形式:
: ${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?}
构造可移植回版本7 UNIX和Bourne Shell(1978或其附近)。的${var:?}
构造稍晚一些:我认为它是在1981年左右的System III UNIX中使用的,但在此之前它可能已经在PWB UNIX中使用了。因此,它位于Korn Shell和POSIX Shell(特别是Bash)中。
它通常在shell的手册页的Parameter Expansion部分中记录。例如,bash
手册说:
${parameter:?word}
如果为空或未设置,则显示错误。如果parameter为null或未设置,则将word的扩展名(或如果不存在word则显示一条消息)写入标准错误,并且如果shell不是交互式的,则退出shell。否则,将替换参数的值。
冒号命令
我可能应该补充一点,冒号命令只是对它的参数求值,然后成功。这是原始的shell注释符号(在' #
'到行尾)。长期以来,Bourne shell脚本的首字符是冒号。C Shell将读取脚本并使用第一个字符来确定它是用于C Shell(#
“哈希”)还是Bourne Shell(:
“冒号”)。然后内核参与进来,并增加了对' #!/path/to/program
'的支持,而Bourne shell得到了' #
'注释,冒号约定就此搁置了。但是,如果遇到以冒号开头的脚本,现在您将知道原因。
双引号的位置
布隆在评论中问:
对这个讨论有什么想法吗?https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749
讨论的要点是:
…但是,当我使用shellcheck
它(版本0.4.1)时,收到以下消息:
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}"
为了说明原因,请研究以下内容。请注意,该:
命令不会回显其参数(但是shell会评估参数)。我们想查看参数,因此下面的代码printf "%s\n"
代替:
。
$ mkdir junk
$ cd junk
$ > abc
$ > def
$ > ghi
$
$ x="*"
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
abc
def
ghi
$ unset x
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
bash: x: You must set x
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
bash: x: You must set x
$ x="*"
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
*
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
abc
def
ghi
$ x=
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$ unset x
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$
请注意,当整个表达式不在双引号中时,in的值$x
将首先扩展到*
文件名列表。这是shellcheck
建议应修复的问题。我尚未验证它是否不反对将表达式用双引号引起来的形式,但这是一个合理的假设,那就是可以。