函数内的函数不返回预期值

时间:2014-11-04 15:03:51

标签: linux bash function

我的最终目标是处理配置文件并在文件中的特定位置添加条目,即在特定行中。

正如您在下面列出的shell脚本中看到的那样(在 Linux (SLES 11)中运行),我使用了两个函数:

  1. getLine返回我要添加条目的行
  2. UserEntry基本上将条目写入指定的行。
  3. (欢迎以任何其他方式提出建议。)

    我面临的问题是,当我从getLine(方法1)内拨打UserEntry时,getLine不会返回任何值。基本上grep -q -v之前的行是空的!

    我必须从主脚本(方法2)单独调用它们,即首先调用getLine,然后调用UserEntry作为参数传递来自getLine的变量值。< / p>

    这种方式有效,但令我困惑的是为什么第一种方式没有。

    这些是配置文件和bash脚本:

    配置文件snmpd.cnf

    #
    ## SOME STUFF HERE
    #
    blablabla
    
    # Entry type: usmUserEntry
    # Format: usmUserEngineID  (octetString)
    #         Normally localSnmpID.
    #
    #         SOME MORE STUFF HERE
    #
    # usmUserEntry localSnmpID snmpv3user usmHMACMD5AuthProtocol usmDESPrivProtocol nonVolatile coROopsTransTag "md5pass" "despass"
    usmUserEntry localSnmpID snmpv3ops usmHMACSHAAuthProtocol usmAesCfb128Protocol nonVolatile coROopsTransTag "opsauth" "opspriv"
    usmUserEntry localSnmpID snmpv3dev usmHMACSHAAuthProtocol usmAesCfb128Protocol nonVolatile coROopsTransTag "devauth" "devpriv"    
    #
    ## SOME STUFF HERE
    #
    blablabla
    

    Shell脚本addline.sh

    #!/bin/sh
    
    CIAGT_CNF=./snmpd.cnf
    Username=FooDoe
    AuthPasswd=A^thP@swd
    EncrKey=3ncrKev
    
    getLine() {
        section=0
        currentline=0
        prevline=0
        while read line; do
            echo "$line" | grep -q "$1"
            if [ $? -eq 0  ]; then
                section=1
                continue
            fi
            echo "$line" | grep -q -v "^#"
            ret=$?
            if [ $ret -eq 0  -a $section -eq 1 ]; then
                currentline=`grep -n "^$line" $CIAGT_CNF | cut -f1 -d":"`
                break
            fi
            echo
        done < $CIAGT_CNF
        prevline=`expr $currentline - 1 `
    }
    
    UserEntry() {
        sed "/^usmUserEntry localSnmpID /d" $CIAGT_CNF > /tmp/sed$$
        cat /tmp/sed$$ > $CIAGT_CNF && rm /tmp/sed$$
    
        ## Calling getLine() from within UserEntry() DID NOT work (was returning all lines)
        ## getLine "^# Entry type: usmUserEntry"
    
        ## sed "${prevline}a\        ## Uncomment this if you call getLine() above
        sed "${1}a\
        usmUserEntry localSnmpID $Username usmHMACSHAAuthProtocol usmAesCfb128Protocol nonVolatile coROopsTransTag \"$AuthPasswd\" \"$EncrKey\"\\
        usmUserEntry localSnmpID public usmNoAuthProtocol usmNoPrivProtocol nonVolatile coROopsTransTag - -" $CIAGT_CNF > /tmp/sed$$
        cat /tmp/sed$$ > $CIAGT_CNF
    }
    
    ## MAIN
    
    ## Method 1
    ## NOTE: Uncomment "getline ..." in UserEntry()
    ## Calling getLine() from within UserEntry() DID NOT work (was returning all lines)...
    ## UserEntry
    
    ## Method 2 (workaround)
    ## ... so we have to call getLine() first and then UserEntry() passing the value of
    ## $prevline as a parameter
    getLine "^# Entry type: usmUserEntry"
    UserEntry $prevline
    

1 个答案:

答案 0 :(得分:0)

这里有你的bash代码。它在以usmUserEntry localSnmpID开头的第一行之前插入一对行。配置文件$CIAGT_CNF中的所有其他行都将复制到/tmp/sed$$文件

typeset -i inserted=0
while read line
do
     read f1 f2 _ <<<"${line}"

     if   [ "${f1}${f2}" = usmUserEntrylocalSnmpID ]
     then
          if   [ "$inserted" -eq 0 ]
          then
               echo "
usmUserEntry localSnmpID $Username usmHMACSHAAuthProtocol usmAesCfb128Protocol nonVolatile coROopsTransTag \042$AuthPasswd\042 \042$EncrKey\042
usmUserEntry localSnmpID public usmNoAuthProtocol usmNoPrivProtocol nonVolatile coROopsTransTag - -
"
               inserted=1
          fi
     fi
     # Prints the original text line 
     echo "$line"
done < "$CIAGT_CNF" > /tmp/sed$$

更新时间:2014-11-06

typeset -i inserted=0
while read line
do
     read f1 f2 f3 f4 _ <<<"${line}"

     if   [ "${f1} ${f2} ${f3} ${f4}" = "# Entry type: usmUserEntry" ]
     then
          echo "$line"

          # Read and print every line starting with '#'
          while read line
          do
               read f1 _ <<<"${line}"
               if   [ "${f1#'#'}" = "${f1}" ]
               then
                    # Exit the inner loop When the first
                    # non-starting '#' line is found.

                    break
               fi
               echo "$line"
          done

          if   [ "$inserted" -eq 0 ]
          then
               echo "
usmUserEntry localSnmpID $Username usmHMACSHAAuthProtocol usmAesCfb128Protocol nonVolatile coROopsTransTag \042$AuthPasswd\042 \042$EncrKey\042
usmUserEntry localSnmpID public usmNoAuthProtocol usmNoPrivProtocol nonVolatile coROopsTransTag - -
"
               inserted=1
          fi
     fi

     # Prints the original text line 
     echo "$line"
done < "$CIAGT_CNF" > /tmp/sed$$

祝你好运