如何检查变量是否存在并与busybox中的字符串进行比较?

如何检查变量是否存在并与busybox中的字符串进行比较?

我想用类似的东西

if [[ ! -z "$ENV" && $ENV == 'production' ]]; then echo "production"; else echo "dev"; fi

但在 BusyBox 中它不起作用:(

sh: 1: [[: not found

看起来任何组合 AND 或 OR 在进入 busybox 的 IF 语句中都不起作用

答案1

[[...]]是一种 Korn shell 构造,也受bash和支持,zsh但不是标准sh构造(并且不受任何其他 shell 支持)。

busybox sh基于ash它实现了 POSIX 规范的一个子集sh(在 POSIX 语言环境中,它在很大程度上兼容),并且具有很少的扩展,特别是,不是这个。

2019年编辑。现在,当使用和[[...]]构建时,busybox ash 也支持ksh 的有限子集以及.ASH_TESTASH_BASH_COMPATyash

无论如何,在编写sh脚本时,您应该遵守 POSIXsh规范。使用的脚本[[...]]应该调用ksh,bashzsh显式调用。bash也是一个主要与 POSIX sh 兼容的 shell,但具有更多扩展(包括这个)。

测试X非空,然后等于就production没有意义了。如果X== production,那么显然它不为空。

使用 POSIX shell 和实用程序进行字符串比较,您有几个选项,在这种情况下最明显的是:

  • [实用程序又名test,通常内置在 shell 中:

      if [ "$var" = production ]; then
        echo PROD
      fi
    
  • 构造case

      case $var in
        production) echo PROD;;
        "") echo EMPTY;;
        *) echo non-PROD;;
      esac
    

现在,您可能想检查变量是否是(与非空相反),在取消引用它之前,在启用该nounset选项的情况下(使用set -uorset -o nounset或 with#! /bin/sh -u作为 she-bang 行),否则如果未设置a[ "$ENV" = production ]将导致 shell 退出。$ENV为此,您需要这样做:

if [ "${var+set}" = set ] && [ "$var" = production ]; then
  echo PROD
fi

(您应该避免使用-a [AND 运算符,因为它已被弃用且不可靠)。

虽然更好、更规范的方法是:

if [ "${var-}" = production ]; then
  echo PROD
fi

nounset不触发${var+string}${var-string}扩展。如果设置了变量,则${var-}扩展为内容,否则扩展为空字符串。$var

其他一些注意事项:

$ENV是一个特殊变量sh。当以交互方式启动时,它被视为从中读取初始化的文件的路径(相当于~/.bashrcfor bash)。您不应该将其用于其他目的。

您会发现一些旧的 Unix shell 脚本文献建议使用[ "x$var" = xproduction ][ production = "$var" ]进行字符串比较。这是为了克服[aka实用程序的一些旧版本中的错误,这些错误被诸如,或 的test某些值混淆。现代系统不需要它,但对于非常旧的系统需要记住这一点。无论如何,该构造不存在此类问题。$var!(-ncase

其他可以进行字符串比较的 POSIX 实用程序包括exprawk

 awk_equal() { awk 'BEGIN{exit(!(""ARGV[1] == ""ARGV[2]))}' "$1" "$2"; }
 expr_equal() { expr "x $1" = "x $2" > /dev/null; }

 if awk_equal "$var" production; then
   echo PROD
 fi
 if expr_equal "$var" production; then
   echo PROD
 fi

请注意,需要""在值前面加上 withawk以确保我们获得字符串比较(否则1将被视为等于01or 1e0),x出于expr同样的原因,还要避免值作为expr运算符出现问题。

对于awkand expr(至少 POSIXly),它们并不是真正的平等运算符,而是测试两个操作数是否具有相同的排序顺序,这不一定是同一件事。例如,在我的系统上,expr_equal ② ③返回 true,因为 ② 和 ③ 都没有定义的排序顺序。一些awk实现(如gawkmawk和 busybox)awk会忽略 POSIX 要求,而是进行简单的字节到字节比较。

无论如何,我想不出有什么好的理由让你更喜欢这些[而不是case这里。

答案2

您可以使用旧[语法

if [ -n "$ENV" -a "$ENV" = 'production' ]

(请注意,我使用-n而不是! -z因为它读起来更容易,但它是同一件事)。

或者我们可以通过强制字符串具有值来简化为更旧的语法:

if [ "x$ENV" = 'xproduction' ]

最后,-n测试可能并不真正需要,你可以这样做

if [ "$ENV" = 'production' ]

相关内容