我有一些Unix shell脚本,我需要在开始做之前检查某些环境变量是否已设置,所以我做了这样的事情:
if [ -z "$STATE" ]; then
echo "Need to set STATE"
exit 1
fi
if [ -z "$DEST" ]; then
echo "Need to set DEST"
exit 1
fi
这是很多打字 . 是否有更优雅的习惯用于检查是否设置了一组环境变量?
编辑:我应该提到这些变量没有有意义的默认值 - 如果没有设置脚本,脚本应该输出错误 .
14 回答
这也可以是一种方式:
http://unstableme.blogspot.com/2007/02/checks-whether-envvar-is-set-or-not.html
我一直用:
我担心的不是那么简洁 .
在CSH下你有$?STATE .
bash
4.2引入了-v
运算符,该运算符测试名称是否设置为任何值,甚至是空字符串 .如果
MyVariable
已设置且不为null,则它将重置变量值(=没有任何反应) .否则,
MyVariable
设置为SomeDefault
.以上将尝试执行
${MyVariable}
,所以如果你只想设置变量do:当然最简单的方法是将
-u
开关添加到shebang(脚本顶部的行),假设您正在使用bash
:#!/bin/sh -u
如果任何未绑定的变量潜伏在内,这将导致脚本退出 .
在我看来,最简单和最兼容的检查 for #!/bin/sh 是:
同样,这是针对/ bin / sh的,并且在旧的Solaris系统上也是兼容的 .
对于像我这样的未来人,我想向前迈出一步并参数化var名称,这样我就可以遍历变量大小的变量名称列表:
$?
语法非常简洁:您的问题取决于您使用的shell .
伯恩贝壳对你所追求的东西的影响很小 .
但...
它确实有效,几乎无处不在 .
试着远离csh . 与Bourne外壳相比,它增加了它所添加的铃声和口哨声,但它现在真的吱吱作响 . 如果您不相信我,请尝试在csh中分离出STDERR! ( - :
这里有两种可能性 . 上面的例子,即使用:
这是你第一次需要引用$ MyVariable . 这需要环境 . var MyVariable,如果当前未设置,则将SomeDefault的值赋给变量供以后使用 .
您还有可能:
它只是将SomeDefault替换为您使用此构造的变量 . 它不会将值SomeDefault赋值给变量,并且在遇到此语句后,MyVariable的值仍为null .
试试这个:
我倾向于加载登录shell中的函数,而不是使用外部shell脚本 . 我使用这样的东西作为辅助函数来检查环境变量而不是任何设置变量:
参数扩展
显而易见的答案是使用参数扩展的一种特殊形式:
或者,更好(请参阅下面的“双引号位置”部分):
第一个变体(仅使用
?
)需要设置STATE,但是STATE =“”(空字符串)是正确的 - 不完全是你想要的,而是替代和旧的表示法 .第二个变体(使用
:?
)要求设置DEST并且不为空 .如果您不提供任何消息,则shell会提供默认消息 .
${var?}
构造可以移植到版本7 UNIX和Bourne Shell(1978或其左右) .${var:?}
构造稍微更近一些:我认为它大约是1981年的System III UNIX,但在此之前可能已经在PWB UNIX中了 . 因此它位于Korn Shell和POSIX shell中,特别包括Bash .它通常记录在shell的手册页中,名为Parameter Expansion . 例如,
bash
手册说:科隆司令部
我应该补充一点,冒号命令只是对其参数进行评估然后成功 . 这是原始的shell评论符号(在'
#
' to end of line). For a long time, Bourne shell scripts had a colon as the first character. The C Shell would read a script and use the first character to determine whether it was for the C Shell (a '#
' hash) or the Bourne shell (a ':
' colon). Then the kernel got in on the act and added support for '#!/path/to/program
' and the Bourne shell got '#
'评论之前,冒号 Session 被排除在外 . 但是如果你遇到一个以冒号开头的剧本,现在你就会明白为什么 .双引号的位置
blong在comment中询问:
讨论的要点是:
简短的回答是“按照
shellcheck
建议”:为了说明原因,请研究以下内容 . 请注意,
:
命令不会回显其参数(但shell会评估参数) . 我们想查看参数,因此下面的代码使用printf "%s\n"
代替:
.注意当整个表达式不是双引号时,
$x
中的值如何扩展到第一个*
然后是文件名列表 . 这是shellcheck
建议应该修复的内容 . 我没有验证它不反对表达式用双引号括起来的形式,但是它是合理的假设它可以 .我们可以编写一个很好的断言来同时检查一堆变量:
示例调用:
输出:
上述解决方案都不适用于我的目的,部分原因是我在开始冗长的流程之前检查环境中是否需要设置的开放式变量列表 . 我最终得到了这个: