将BASH脚本转换为在SH上运行(通过BusyBox)
我有一台华硕路由器,运行的是BusyBox附带的最新版本 我需要运行一个用BASH编写的脚本—它是的一个改编版—但由于以下错误而无法运行:将BASH脚本转换为在SH上运行(通过BusyBox),bash,sh,parameter-expansion,Bash,Sh,Parameter Expansion,我有一台华硕路由器,运行的是BusyBox附带的最新版本 我需要运行一个用BASH编写的脚本—它是的一个改编版—但由于以下错误而无法运行:第41行:语法错误:错误替换 使用以下错误检查脚本: Line 41: for optionvarname in ${!foreign_option_*} ; do ^-- SC3053: In POSIX sh, indirect expansion is undefined.
第41行:语法错误:错误替换
使用以下错误检查脚本:
Line 41:
for optionvarname in ${!foreign_option_*} ; do
^-- SC3053: In POSIX sh, indirect expansion is undefined.
^-- SC3056: In POSIX sh, name matching prefixes are undefined.
Line 42:
option="${!optionvarname}"
^-- SC3053: In POSIX sh, indirect expansion is undefined.
以下是导致问题的线路:
${!foreign_option_*}中optionvarname的;第41行
option=“${!optionvarname}”第42行
#用$option做一些事情。。。
完成
如果我的理解是正确的,那么原始脚本只是对所有名称以foreign\u option\u开头的变量执行一些操作
但是,据我所知,${!foreign_option_*}
和${!optionvarname}
构造都是特定于BASH的,不符合POSIX,因此不可能直接进行“BASH到sh”的代码转换
我试图创建一个指向busybox
的/bin/bash
符号链接,但出现了只读文件系统
错误
那么,如何让这个脚本在我的路由器上运行呢?我只看到两个选项,但我不知道如何实现这两个选项:
让BusyBox将脚本解释为BASH而不是SH-我可以为此使用特定的shebang吗?
- 似乎是最快的选择,但前提是BusyBox有一个BASH的“完整”实现
修改脚本代码以不使用BASH细节。
- 这是比较安全的,但是因为SH没有“收集以X开头的所有变量”,我该怎么做呢
如何让此脚本在路由器上运行
这很容易,或者:
- 在路由器上安装bash或
- 将脚本移植到busybox/posix兼容的shell
让BusyBox将脚本解释为BASH而不是SH-我可以为此使用特定的shebang吗
那没有道理。Busybox附带了ash
shell解释器,bash就是bash。Bash可以解释Bash扩展,而ash不能解释它们。你不能“让爱管闲事的人解释bash”——汽车不能飞,飞机就是为了这个。如果你想让汽车飞起来,你可以给它加上翅膀,让它飞得更快。makebusybox将脚本解释为BASH而不是SH
的答案是:修补BusyBox并在其中实现所有BASH扩展
Shebang用于在不同的解释器下运行文件。使用#/bin/bash
将调用bash
,这将与busybox相关的任何内容无关,busybox不会参与其中
我怎么做
确定一个不切实际的最大值,迭代名为foreign\u option\u{1…some\u max}
的变量,查看每个变量是否已设置,如果已设置,则继续脚本
for i in $(seq 100); do
optionvarname="foreign_option_${i}"
# https://stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash
if eval "[ -z \"\${${optionvarname}+x}\" ]"; then continue; fi;
如果运气好的话,也许您可以使用设置
输出。如果任何变量包含值为换行符+与正则表达式匹配的字符串,则以下操作将失败:
for optionvarname in $(set | grep -o '^foreign_option_[0-9]\+=' | sed 's/=//'); then
间接扩展很容易被eval
取代:
eval "option=\"\$${optionvarname}\""
如果您真的无法在该路由器上安装Bash,下面是一个可能的解决方法,它似乎适合我在Qnap NAS上的BusyBox:
foreign_option_one=1
foreign_option_two=2
for x in one two; do
opt_var=foreign_option_${x}
eval "opt_value=\$$opt_var"
echo "$opt_var = $opt_value"
done
(但您可能会遇到更多的问题,将BASH脚本移到BuyBox,因此您可能首先考虑替换路由器之类的选项)
如何>代码> SETGRIP-E“^ x”< /代码>以从<代码> x>代码>开始收集变量名?<代码> SH < /C>不提供可变的间接方向,如<代码> ${opopraveNord}。
尝试计算其名称存储在选项varname
中的变量。这是一个bash特有的特性,会导致“糟糕的替换”。。。请注意您的错误消息“在POSIX sh中,间接扩展是未定义的。”--这就是它告诉您的……。@DavidC.Rankin:我解决了这个问题,但遗憾的是,我并不精通bash
/sh
差异和复杂性,以便能够进行正确的转换,因此请求我的路由器提供帮助,/bin/sh
是指向/bin/busybox
的符号链接。我将尝试“不切实际的最大值”建议(而不是set
one),我会让你知道它是如何进行的。