Busybox sh 不会执行 bash 脚本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/50832481/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Busybox sh won't execute the bash script
提问by Nayab Basha Sayed
I have a small script called test.sh
which prints the value based on the index given.
我有一个名为的小脚本test.sh
,它根据给定的索引打印值。
#!/bin/sh
days_in_month=(0 31 28 31 30 31 30 31 31 30 31 30 31)
echo "${days_in_month[]}"
The above code works fine if I execute using bash
.
如果我使用bash
.
$ bash test.sh 1
31
But I need to execute the same script in an embedded board which has sh
as part of Busybox
package. When I run the command in that board, it throws an error.
但是我需要在sh
作为Busybox
包的一部分的嵌入式板中执行相同的脚本。当我在该板上运行命令时,它会引发错误。
$ sh test.sh
test.sh: line 2: syntax error: unexpected "("
I observe that the same error is thrown when I use dash
instead of bash
in Ubuntu system.
我观察到当我使用dash
而不是bash
在 Ubuntu 系统中时抛出相同的错误。
$ dash test.sh
test.sh: line 2: syntax error: unexpected "("
Is there any way that I could change the code so that Busybox sh will execute without any errors?
有什么办法可以更改代码,以便 Busybox sh 执行时不会出现任何错误?
回答by Socowi
Both busybox' sh
(which isash
) and dash do notsupport arrays.
busybox' sh
(即ash
)和破折号都不支持数组。
You could either write a big if-else or switch case statement, or use the following trick. We simulate an array using a single string with spaces as delimiters.
您可以编写一个大的 if-else 或 switch case 语句,或者使用以下技巧。我们使用带有空格作为分隔符的单个字符串来模拟数组。
cut -d ' ' -f "" <<< "31 28 31 30 31 30 31 31 30 31 30 31"
or even more portable:
甚至更便携:
echo "31 28 31 30 31 30 31 31 30 31 30 31" | cut -d ' ' -f ""
Another workaround is to abuse the script's positional parameters as seen in this answer.
另一种解决方法是滥用脚本的位置参数,如本答案所示。
回答by Kusalananda
/bin/sh
in general does not support arrays, apart from the list of positional parameters.
/bin/sh
除了位置参数列表外,一般不支持数组。
Let's use that:
让我们使用它:
#/bin/sh
pos=
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' ""
This first picks out the number from the command line and puts it into pos
. Then it sets the positional parameters that you had in your array. By shifting pos - 1
elements off this array, we have the wanted number in $1
.
这首先从命令行中挑选出数字并将其放入pos
. 然后它设置您在数组中的位置参数。通过pos - 1
从这个数组中移出元素,我们在 中得到了想要的数字$1
。
This would work even if the list contained strings with spaces in them, such as in
即使列表包含带有空格的字符串,这也会起作用,例如
#/bin/sh
pos=
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' ""
The other way to solve this with /bin/sh
is with a case
statement:
解决此问题的另一种方法/bin/sh
是使用case
语句:
case 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' "" >&2
exit 1
esac
回答by Sidepipe
It's quite useful to use eval
in this situation. You can simply define a couple of functions:
eval
在这种情况下使用它非常有用。您可以简单地定义几个函数:
assign_element() { eval "__ARR__=\"\""; }
get_element() { eval "echo $__ARR__"; }
You can then do:
然后你可以这样做:
assign_element days_of_week 1 31
and
和
$ get_element days_of_week 1
31
Of course, all this is really doing is creating separate variables whose names are of a fixed format relating to the array name and element. Depending on the situation you can make those variable names more complex to avoid clashes, and there's no reason for indices to be numeric. It's also trivial to assign a list of values to numeric indices using a small script to more closely match your original question, something like:
当然,这一切真正做的是创建单独的变量,其名称具有与数组名称和元素相关的固定格式。根据情况,您可以使这些变量名称更复杂以避免冲突,并且没有理由将索引设为数字。使用小脚本将值列表分配给数字索引以更紧密地匹配您的原始问题也很简单,例如:
assign_list() {
local N=0 NAME=
while [ -n "" ] ; do
assign_element "$NAME" $N ""
shift
N=$((N + 1))
done
}
Then your initial problem becomes:
那么你最初的问题就变成了:
$ 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