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

use*_*265 8 shell busybox test

我想使用类似的东西

if [[ ! -z "$ENV" && $ENV == 'production' ]]; then echo "production"; else echo "dev"; fi
Run Code Online (Sandbox Code Playgroud)

但在 BusyBox 中它不起作用:(

sh: 1: [[: not found
Run Code Online (Sandbox Code Playgroud)

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

Sté*_*las 11

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

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

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

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

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

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

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

if [ "${var+set}" = set ] && [ "$var" = production ]; then
  echo PROD
fi
Run Code Online (Sandbox Code Playgroud)

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

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

if [ "${var-}" = production ]; then
  echo PROD
fi
Run Code Online (Sandbox Code Playgroud)

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

其他一些注意事项:

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

您会发现一些旧的 Unix shell 脚本文献推荐使用[ "x$var" = xproduction ][ production = "x$var" ]进行字符串比较。这是克服一些老版本的漏洞[,并test认为是由一些混淆值公用事业$var!(-n。现代系统不应该需要它,但是对于非常旧的系统需要记住一些东西。在任何情况下,case构造都没有这种问题。

其他可以进行字符串比较的 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
Run Code Online (Sandbox Code Playgroud)

请注意,需要预先设置""与价值观awk,以确保我们得到一个字符串比较(否则1会被认为等于011e0),以及xexpr出于同样的原因,也避免与价值观是问题expr经营。

对于awkexpr(至少是 POSIXly),它们并不是真正的相等运算符,而是测试两个操作数是否具有相同的排序顺序,这可能不一定是同一件事。例如,在 may 系统上,expr_equal ? ?返回 true,因为两者都没有?也不是?有明确的排序顺序。一些awk实现,如gawk,mawk和 busyboxawk忽略了 POSIX 要求,而是进行简单的字节到字节比较。

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


Ste*_*ris 7

您可以使用旧[语法

if [ -n "$ENV" -a "$ENV" = 'production' ]
Run Code Online (Sandbox Code Playgroud)

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

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

if [ "x$ENV" = 'xproduction' ]
Run Code Online (Sandbox Code Playgroud)

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

if [ "$ENV" = 'production' ]
Run Code Online (Sandbox Code Playgroud)