2009-04-30 139 views
1

这是一个非常简单的bash脚本中,我写道:修改while循环shell变量不能按预期

#!/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运行它。

考虑这两个示例文件:

items.txt

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 

问题:

为什么脚本打印“总未找到的项目:0”?它在循环的每个回显上打印当前总数(都是NOT_FOUND变量)。

是否有这个shell脚本一些不好的做法?地点和原因?

回答

6

管你用这里:

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解释。希望这可以帮助。

随着FAQ解释说,在特定的情况下,也可以重写它,所以它读取:

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} 

倾向于第二种选项,在这种情况下,因为这将摆脱一个“无用的使用猫的“:)

+0

由于它的作品!我第一次听到关于子shell :-) – sourcerebels 2009-04-30 16:26:39

0

使用expr做数学

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

1 

@litb是正确的,你需要在你的主脚本来更新NOT_FOUND,而不是被催生子壳管道命令。

+0

感谢您的答复,我测试@litb第二个解决方案,它的工作原理 – sourcerebels 2009-04-30 16:27:44