Busybox sh不会执行bash脚本

时间:2018-06-13 08:26:27

标签: bash sh busybox dash-shell

我有一个名为test.sh的小脚本,它根据给定的索引打印值。

#!/bin/sh
days_in_month=(0 31 28 31 30 31 30 31 31 30 31 30 31)
echo "${days_in_month[$1]}"

如果我使用bash执行上述代码。

$ bash test.sh 1
31

但是我需要在嵌入式电路板中执行相同的脚本,该电路板sh作为Busybox包的一部分。当我在该板上运行命令时,它会抛出错误。

$ sh test.sh
test.sh: line 2: syntax error: unexpected "("

我发现在Ubuntu系统中使用dash而不是bash时会抛出同样的错误。

$ dash test.sh
test.sh: line 2: syntax error: unexpected "("

有没有什么方法可以更改代码,以便Busybox sh可以执行而没有任何错误?

3 个答案:

答案 0 :(得分:2)

busybox' shash)和破折号支持数组。

您可以编写一个大的if-else或switch case语句,也可以使用以下技巧。我们使用带有空格作为分隔符的单个字符串来模拟数组。

cut -d ' ' -f "$1" <<< "31 28 31 30 31 30 31 31 30 31 30 31"

甚至更便携:

echo "31 28 31 30 31 30 31 31 30 31 30 31" | cut -d ' ' -f "$1"

另一种解决方法是滥用脚本的位置参数,如this answer中所示。

答案 1 :(得分:2)

除了位置参数列表之外,

/bin/sh通常不支持数组。

让我们使用:

#/bin/sh

pos=$1

if [ "$pos" -lt 1 ] || [ "$pos" -gt 12 ]; then
    printf 'No such month: %s\n' "$pos" >&2
    exit 1
fi

set -- 31 28 31 30 31 30 31 31 30 31 30 31
shift "$(( pos - 1 ))"
printf '%s\n' "$1"

首先从命令行中选出数字并将其放入pos。然后它设置您在数组中的位置参数。通过将pos - 1元素移出此数组,我们在$1中有所需的数字。

即使列表中包含带空格的字符串,例如在

中也是如此
#/bin/sh

pos=$1

if [ "$pos" -lt 1 ] || [ "$pos" -gt 12 ]; then
    printf 'No such month: %s\n' "$pos" >&2
    exit 1
fi

set -- "thirty one" "twenty eight" "thirty one" etc.
shift "$(( pos - 1 ))"
printf '%s\n' "$1"

使用/bin/sh解决此问题的另一种方法是使用case语句:

case $1 in
    2)
        echo 28 ;;
    4|6|9|11)
        echo 30 ;;
    1|3|5|7|8|10|12)
        echo 31 ;;
    *)
        print 'No such month: %s\n' "$1" >&2
        exit 1
esac

答案 2 :(得分:0)

在这种情况下使用eval非常有用。您可以简单地定义几个函数:

assign_element() { eval "__ARR_$1_$2=\"$3\""; }
get_element() { eval "echo \$__ARR_$1_$2"; }

您可以执行以下操作:

assign_element days_of_week 1 31

$ get_element days_of_week 1
31

当然,这实际上是创建单独的变量,这些变量的名称具有与数组名称和元素有关的固定格式。根据情况,可以使这些变量名称更复杂以避免冲突,并且没有理由将索引设为数字。使用小脚本将值列表分配给数字索引也很麻烦,例如,类似于:

assign_list() {
    local N=0 NAME=$1
    while [ -n "$2" ] ; do
        assign_element "$NAME" $N "$2"
        shift
        N=$((N + 1))
    done
}

然后您的最初问题变为:

$ assign_list days_in_month 0 31 28 31 30 31 30 31 31 30 31 30 31
$ get_element days_in_month 1
31