什么是检查环境变量在Unix中shellscript里设置一个简洁的方式? [英] What's a concise way to check that environment variables are set in Unix shellscript?

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

问题描述

我有,我需要检查之前,我开始做的东西一定的环境变量设置一些UNIX shell脚本,所以我做这样的事情:

 如果[-z$ STATE];然后
    回声需要设置状态
    1号出口
科幻如果[-z$ DEST];然后
    回声需要设置DEST
    1号出口
科幻

这是很多打字。有没有检查一组环境变量设置一个更优雅的成语?

编辑:我应该指出,这些变量没有任何有意义的默认值 - 脚本应该报错了,如果任何都没有设置


解决方案

参数扩展

明显的答案是使用参数扩展的特殊形式之一:

 :$ {STATE需要设置状态?}
:$ {DEST:需要设置DEST非空}

或者,更好的(参见双引号的位置一节):

 :$ {STATE需要设置状态呢?}
:$ {DEST:需要设置DEST非空}

第一个变种(?只使用 ),要求国家进行设置,但STATE =(空字符串)是OK—不正是你想要的,但替代和老年人的符号。

第二个变种(使用)。DEST要求要设置和非空

如果您提供任何消息,外壳提供了默认的消息。

$ {VAR?} 构造是便携式回版本7 UNIX和Bourne shell(1978点左右)。在 $ {VAR:} 构造稍最近:我认为这是在System III UNIX大约1981年,但它可能已在PWB UNIX之前。因此,在Korn shell中,并且在POSIX的炮弹,其中包括特别猛砸。

它通常是记录在shell的手册页在一节名为参数扩展。例如,庆典手册说:


  $ {参数:?单词}


  
  

显示错误,如果空或取消。如果参数为null或取消,文字的扩大(或一条信息,影响,如果字不是present)被写入标准错误和外壳,如果不是交互式的,退出。否则,参数的值是取代


冒号命令

我也许应该补充一点,冒号命令只是有其论据进行评估,然后成功。这是原来的外壳评论符号(前'行尾)。长期以来,Bourne shell的脚本有一个冒号作为第一个字符。 C shell中会读剧本和使用的第一个字符以确定它是否为C壳牌(A '哈希)或Bourne shell的(一个'冒号)。那么内核得到了在这项法案,并增加了支持#!/路径/要/程序和Bourne shell了的意见和结肠约定了的手下败将。但是,如果你遇到了一个冒号开头的脚本,现在你就会知道为什么。


双引号的位置

blong 要求在<一个href=\"http://stackoverflow.com/questions/307503/whats-the-best-way-to-check-that-environment-variables-are-set-in-unix-shellscr/307735?noredirect=1#comment53771660_307735\">comment:


  

在这个讨论有什么想法? <一href=\"https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749\">https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749


讨论的主旨在于:


  

...然而,当我 shellcheck 它(与0.4.1版),我得到这个消息:

 在script.sh 13号线:
:$ {FOO:环境变量FOO'必须设置和非空}
  ^ - SC2086:双引号,以prevent通配和分词。

这是我应该在这种情况下做什么有什么建议?


简短的回答是做的 shellcheck 建议:

 :$ {STATE需要设置状态呢?}
:$ {DEST:需要设置DEST非空}

要说明为什么,学习以下。请注意,命令不会回其参数(但外壳不评估参数)。我们希望看到的参数,所以code以下使用的printf%S \\ N代替

  $垃圾的mkdir
$ CD垃圾
$&GT; ABC
$&GT; DEF
$&GT; GHI
$
$ X =*
$ printf的%S \\ n$ {X:你必须设置X}#粗心;不建议
ABC
DEF
GHI
$未设置点¯x
$ printf的%S \\ n$ {X:你必须设置X}#粗心;不建议
bash中:X:必须集合X
$ printf的%S \\ n$ {X:你必须设置X}#小心:应使用
bash中:X:必须集合X
$ X =*
$ printf的%S \\ n$ {X:你必须设置X}#小心:应使用
*
$ printf的%S \\ n$ {X:你必须设置X}#不太够小心
ABC
DEF
GHI
$ X =
$ printf的%S \\ n$ {X:你必须设置X}#不太够小心
bash中:X:必须集合X
$未设置点¯x
$ printf的%S \\ n$ {X:你必须设置X}#不太够小心
bash中:X:必须集合X
$

请注意如何在 $ X 的值被扩展为第一个 * ,然后文件名的列表时,整体前pression是不是在双引号。这是 shellcheck 的建议应该是固定的。我没有验证,它不反对,其中前pression是双引号括起来的形式,但它是一个合理的假设,这将是确定。

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?

EDIT: 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}"

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.

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

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

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.

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

${parameter:?word}

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.

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.


Position of double quotes

blong asked in a comment:

Any thoughts on this discussion? https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749

The gist of the discussion is:

… 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?

The short answer is "do as shellcheck suggests":

: "${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\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
$ 

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中shellscript里设置一个简洁的方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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