检查在Unix Shell脚本中设置环境变量的简洁方法是什么? [英] What's a concise way to check that environment variables are set in a Unix shell script?

查看:86
本文介绍了检查在Unix Shell脚本中设置环境变量的简洁方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些Unix shell脚本,在开始做事之前,我需要检查某些环境变量是否已设置,所以我要执行以下操作:

I've got a few Unix shell scripts where I need to check that certain environment variables are set before I start doing stuff, so I do this sort of thing:

if [ -z "$STATE" ]; then
    echo "Need to set STATE"
    exit 1
fi  

if [ -z "$DEST" ]; then
    echo "Need to set DEST"
    exit 1
fi

很多类型的输入.有没有更优雅的习惯来检查是否设置了一组环境变量?

which is a lot of typing. Is there a more elegant idiom for checking that a set of environment variables is set?

我应该提到这些变量没有有意义的默认值-如果未设置任何脚本,则脚本应该出错.

I should mention that these variables have no meaningful default value - the script should error out if any are unset.

推荐答案

参数扩展

显而易见的答案是使用参数扩展的一种特殊形式:

Parameter Expansion

The obvious answer is to use one of the special forms of parameter expansion:

: ${STATE?"Need to set STATE"}
: ${DEST:?"Need to set DEST non-empty"}

或者更好(请参见下面的双引号的位置"部分):

Or, better (see section on 'Position of double quotes' below):

: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"

第一个变体(仅使用?)需要设置STATE,但是STATE ="" (一个空字符串)还可以-并非您要的完全是您想要的,而是其他的和较旧的表示法.

The first variant (using just ?) requires STATE to be set, but STATE="" (an empty string) is OK — not exactly what you want, but the alternative and older notation.

第二个变体(使用:?)要求设置DEST,并且不为空.

The second variant (using :?) requires DEST to be set and non-empty.

如果您未提供任何消息,则外壳程序会提供默认消息.

If you supply no message, the shell provides a default message.

${var?}构造可移植回版本7 UNIX和Bourne Shell(1978或其前后版本). ${var:?}构造稍晚一些:我认为它是在1981年左右的System III UNIX中使用的,但在此之前它可能已经在PWB UNIX中使用了.因此,它位于Korn Shell和POSIX Shell中,尤其是在Bash中.

The ${var?} construct is portable back to Version 7 UNIX and the Bourne Shell (1978 or thereabouts). The ${var:?} construct is slightly more recent: I think it was in System III UNIX circa 1981, but it may have been in PWB UNIX before that. It is therefore in the Korn Shell, and in the POSIX shells, including specifically Bash.

通常在shell手册页的

It is usually documented in the shell's man page in a section called Parameter Expansion. For example, the bash manual says:

${parameter:?word}

如果为Null或未设置,则显示错误.如果parameter为null或未设置,则将word的扩展名(或如果不存在word则显示一条消息)写入标准错误,并且如果shell不是交互式的,则退出shell.否则,将替换参数的值.

Display Error if Null or Unset. If parameter is null or unset, the expansion of word (or a message to that effect if word is not present) is written to the standard error and the shell, if it is not interactive, exits. Otherwise, the value of parameter is substituted.

冒号命令

我可能应该补充一点,即冒号命令只是对它的参数求值,然后成功.它是原始的shell注释符号(在行末尾的#之前).长期以来,Bourne shell脚本的首字符是冒号. C Shell将读取脚本并使用第一个字符来确定它是用于C Shell("<​​c5>"哈希)还是Bourne Shell("<​​c7>"冒号).然后内核参与进来,并增加了对'#!/path/to/program'的支持,而Bourne shell得到了'#'注释,冒号约定就被搁置了.但是,如果您遇到以冒号开头的脚本,那么现在您将知道原因了.

The Colon Command

I should probably add that the colon command simply has its arguments evaluated and then succeeds. It is the original shell comment notation (before '#' 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 '#' comments, and the colon convention went by the wayside. But if you come across a script that starts with a colon, now you will know why.

对此讨论有何想法? https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749

讨论的重点是:

...但是,当我shellcheck它(版本为0.4.1)时,我收到此消息:

… However, when I shellcheck it (with version 0.4.1), I get this message:

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.

在这种情况下我应该怎么做?

Any advice on what I should do in this case?

简短的答案是按照shellcheck的建议做":

The short answer is "do as shellcheck suggests":

: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"

要说明原因,请研究以下内容.请注意,:命令不会回显其参数(但是shell会评估参数).我们希望看到参数,因此下面的代码使用printf "%s\n"代替:.

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\n" in place of :.

$ 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
$ 

请注意在整体表达式不在双引号中时,如何将$x中的值扩展到第一个*,然后扩展到文件名列表.这是shellcheck建议的内容,应予以修复.我尚未验证它是否不反对将表达式用双引号引起来的形式,但这是一个合理的假设,即可以.

Note how the value in $x is expanded to first * and then a list of file names when the overall expression is not in double quotes. This is what shellcheck is recommending should be fixed. I have not verified that it doesn't object to the form where the expression is enclosed in double quotes, but it is a reasonable assumption that it would be OK.

这篇关于检查在Unix Shell脚本中设置环境变量的简洁方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆