曲径通幽论坛

标题: [functions.sh]config_foreach [打印本页]

作者: beyes    时间: 2014-12-5 15:35
标题: [functions.sh]config_foreach
在 /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() 函数的最后一句里正是对这个变量进行了赋值:
  1. 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() 中最后一条语句:
  1. eval "$___function \"\$section\" \"\$@\""
复制代码

这条语句就是调用自定义的回调函数。






欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2