bash - 将 BASH 脚本转换为在 SH 上运行(通过 BusyBox)
问题描述
我有一个运行最新版本FreshTomato的华硕路由器- BusyBox 附带。
我需要运行一个考虑到 BASH 的脚本——它是这个脚本的改编版——但它无法运行并出现以下错误: line 41: syntax error: bad substitution
使用shellcheck.net检查脚本会产生以下错误:
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.
这些是导致问题的行:
for optionvarname in ${!foreign_option_*} ; do # line 41
option="${!optionvarname}" # line 42
# do some stuff with $option...
done
如果我的理解是正确的,那么原始脚本只是对所有名称以开头的变量做一些事情foreign_option_
但是,据我所知,${!foreign_option_*}
和${!optionvarname}
构造都是 BASH 特定的,并且不兼容 POSIX,因此不可能进行直接的“bash 到 sh”代码转换。
我试图创建一个/bin/bash
指向 的符号链接busybox
,但我得到了Read-only file system
错误。
那么,我怎样才能让这个脚本在我的路由器上运行呢?我只看到两个选项,但我无法弄清楚如何实现:
- 让 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 不能解释它们。你不能“让busybox解释bash”——汽车不会飞,飞机就是为此。如果你想让汽车飞起来,你就给它加翅膀,让它飞得更快。答案Make BusyBox interpret the script as BASH instead of SH
是:修补busybox并在其中实现所有bash扩展。
Shebang 用于在不同的解释器下运行文件。Using#!/bin/bash
将调用bash
,这与任何与busybox相关的内容无关,并且busybox不会参与其中。
我该怎么做?
确定一个不切实际的最大值,遍历名为 的变量foreign_option_{1...some_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;
运气好的话,也许你可以使用set
输出。如果任何变量包含一个值作为换行符 + 与正则表达式匹配的字符串,则以下操作将失败:
for optionvarname in $(set | grep -o '^foreign_option_[0-9]\+=' | sed 's/=//'); then
间接扩展可以很容易地替换为eval
:
eval "option=\"\$${optionvarname}\""
推荐阅读
- javascript - 如果我使用 defaultChecked,排序表列不会改变复选框的位置
- google-closure-compiler - 命令行编译生成的文件比在线版本大
- r - 使用 ggplot geom_smooth 使多条平滑线相对于置信区间填充更加明显
- c# - Azure KeyVault 配置提供程序在更改时重新加载值
- php - 如何在 ACF 转发器字段中的行上循环和回显值编号
- html - 如何水平定位 div 与父 div 的右边框重叠?
- eclipse - 如何配置与maven捆绑的tomcat?
- jdeveloper - Oracle JDeveloper 服务总线
- html - HTML 指定方格图片系统的长宽
- react-native - 想要获取 BottomTabNavigator 单独的组件