代码之家  ›  专栏  ›  技术社区  ›  sourcerebels

修改while循环中的shell变量无法按预期工作

  •  1
  • sourcerebels  · 技术社区  · 17 年前

    #!/bin/bash
    
    ITEM_LIST=items.txt
    LOG_FILE=log.log
    
    TOTAL_ITEMS=$(wc -l ${ITEM_LIST} | awk '{ print $1 }')
    let NOT_FOUND=0
    
    cat ${ITEM_LIST} | while read item; do
    
        grep "${item}" ${LOG_FILE} > /dev/null
        FOUND=${?}
        if [ ${FOUND} -ne 0 ]; then
            let NOT_FOUND=NOT_FOUND+1
            echo "Item not found [${item}] Item not found number: ${NOT_FOUND}"
        fi
    
    done
    
    echo "Total items: ${TOTAL_ITEMS}"
    echo "Total not found items: ${NOT_FOUND}"
    

    我想检查日志文件中是否存在某些项,计算有多少项不存在,并打印某种报告(最后两个)。现在,我正在cygwin bash shell上运行它。

    考虑这两个示例文件:

    first item
    second item
    third item
    fourth item
    fifth item
    

    log.log

    blahblah blah blah first item blah blah blah
    second blah blah item
    blah third item blah
    

    脚本的输出:

    [17:46:38]:/cygdrive/c/Temp/qpa# ./script2.sh 
    Item not found [second item] Item not found number: 1
    Item not found [fourth item] Item not found number: 2
    Total items: 4
    Total not found items: 0
    

    问题:

    这个shell脚本中是否存在一些不好的做法?在哪里,为什么?

    2 回复  |  直到 10 年前
        1
  •  6
  •   Johannes Schaub - litb    17 年前

    此处使用的管道:

    cat ${ITEM_LIST} | ...
    

    之后将在子shell中执行while循环。但这意味着 NOT_FOUND 变量不会在父shell中更新,而只会在执行循环的子shell中更新。

    cat ${ITEM_LIST} | { 
      while read item; do
        grep "${item}" ${LOG_FILE} > /dev/null
        FOUND=${?}
        if [ ${FOUND} -ne 0 ]; then
            let NOT_FOUND=NOT_FOUND+1
            echo "Item not found [${item}] Item not found number: ${NOT_FOUND}"
        fi
      done
    
      echo "Total items: ${TOTAL_ITEMS}"
      echo "Total not found items: ${NOT_FOUND}"
    }
    

    这个问题也在一篇文章中得到了解释 Bash FAQ item . 希望这有帮助。

    如常见问题解答所述,在这种情况下,您还可以将其改写为:

    while read item; do
        grep "${item}" ${LOG_FILE} > /dev/null
        FOUND=${?}
        if [ ${FOUND} -ne 0 ]; then
            let NOT_FOUND=NOT_FOUND+1
            echo "Item not found [${item}] Item not found number: ${NOT_FOUND}"
        fi
    done < ${ITEM_LIST}
    

    在这种情况下,首选第二个选项,因为它将消除一个“对cat的无用使用”:

        2
  •  0
  •   lothar    17 年前

    expr 算算

    NOT_FOUND=0; NOT_FOUND=`expr ${NOT_FOUND} + 1`; echo ${NOT_FOUND}
    
    1
    

    @litb是正确的,您需要更新主脚本中的NOT_,而不是管道命令生成的子shell中的NOT_。

    推荐文章