在 /lib/functions.sh 文件中,config_foreach() 函数用来迭代每一个 section 。下面看它的代码定义:
[Bash shell] 纯文本查看 复制代码 config_foreach() {
local ___function="$1"
[ "$#" -ge 1 ] && shift
local ___type="$1"
[ "$#" -ge 1 ] && shift
local section cfgtype
[ -z "$CONFIG_SECTIONS" ] && return 0
for section in ${CONFIG_SECTIONS}; do
config_get cfgtype "$section" TYPE
[ -n "$___type" -a "x$cfgtype" != "x$___type" ] && continue
eval "$___function \"\$section\" \"\$@\""
done
}
该函数至少得带有一个参数:
1. 一个回调函数,回调函数是一个自定义的函数,必须在调用 config_foreach 之前就定义。回调函数会在每次遇到 section 时被调用执行,这个从上面代码的 eval "$___function \"\$section\" \"\$@\"" (位于 for 中)可以看到。
2. 类型(可选),指定了类型,那么 config_foreach 就只关心该类型的 section (比如 network 中的 interface),而忽略其它的。
3. 附加参数(可选),如果给了这些参数,那么都会一股脑的传递到回调函数之中。
下面给出一段测试代码,考察该函数的具体应用:
[Bash shell] 纯文本查看 复制代码 #!/bin/sh
. /lib/functions.sh
config_load network
handle_interface() {
local iface="$1"
echo $iface
}
config_foreach handle_interface interface
运行输出:
# ./tmp
loopback
lan
wan
wan6
由此可见,它遍历了类型为 interface 的所有 section ,并输出了 section 名。
以操作 /etc/config/network 为例,现在回过头来看一下 config_foreach 的具体代码:
开头部分,分别将回调函数传和类型递给本地变量 ___function 和 ___type。
接着,判断 $CONFIG_SECTIONS 是否为空,为空则返回 0 ([ -z "$CONFIG_SECTIONS" ] && return 0 )。其中,$CONFIG_SECTIONS 的值已经在 config() 和 append() 等函数里获得。
再接着,通过一个循环 for section in ${CONFIG_SECTIONS}; 遍历所有 SECTIONS,比如有 lookback, lan, wan, wan6 等。
接着,使用 config_get 函数 config_get cfgtype "$section" TYPE 获取 section 的类型(比如 interface, globals, switch, switch_vlan 等),并将其赋值给 cfgtype 变量中。这里第 3 个参数 TYPE 是为了使用 config() 函数中导出的相应变量,比如 CONFIG_lookback_TYPE 。在 config() 函数的最后一句里正是对这个变量进行了赋值:
- export ${NO_EXPORT:+-n} "CONFIG_${CONFIG_SECTION}_TYPE=$cfgtype"
复制代码
注意,上面的 $cfgtype 只是 config() 函数里的局部变量,并不是 config_get 里的 cfgtype 。比如在 network 里有这么个定义:config interface lookback ,那么 config() 里的 $cftype 就是 interface 。
在获得 section 的类型名后,再用语句 [ -n "$___type" -a "x$cfgtype" != "x$___type" ] && continue 判断所获得类型是否和 config_foreach() 函数中的类型一致,若是不一致,则重新跳回 for 循环,进行下一个迭代。若是一致,那么调用 config_foreach() 中最后一条语句:
- eval "$___function \"\$section\" \"\$@\""
复制代码
这条语句就是调用自定义的回调函数。
|