2012-07-23 283 views
1

我有一个奇怪的问题与Bash脚本。变量NumTMPara在内部循环中有正确的值,但在循环外部,值为0?变量undefined在循环外部

这里是我的脚本:

echo "packet.txt" 
cat $SRDB_dir/tpcf.dat | sed -e 's/[\t]/;/g' \ 
| while read my_line 
    do 
    PID_SPID=$(echo $my_line | cut -f1 -d';') 
    TPCF_NAME=$(echo $my_line | cut -f2 -d';') 
    NumTMPara=0 
    cat $SRDB_dir/plf.dat | sed -e 's/[\t]/;/g' | grep ";$PID_SPID;" \ 
    | while read my_line2 
     do 
     PCF_NAME=$(echo $my_line2 | cut -f1 -d';') 
     Param_ID=$(cat $destination/tmparam.txt | sed -e 's/[\t]/;/g' | grep ";$PCF_NAME," | cut -f1 -d ';') 
     OFFBYTE=$(echo $my_line2 | cut -f3 -d';') 
     OFFBIT=$(echo $my_line2 | cut -f4 -d';') 

     Myptc=$(grep $PCF_NAME $SRDB_dir/pcf.dat | sed -e 's/[\t]/;/g' | cut -f5 -d';') 
     Mypfc=$(grep $PCF_NAME $SRDB_dir/pcf.dat | sed -e 's/[\t]/;/g' | cut -f6 -d';') 
     WIDTH=$(get_width $Myptc $Mypfc) 

     PCF_RELATED="" 
     PCF_DESCR=$(grep "^$PCF_NAME" $SRDB_dir/pcf.dat | sed -e 's/[\t]/;/g' | cut -f2 -d ';') 
     let NumTMPara=1+${NumTMPara} 

     #here, the value is correctly reported 
     echo -e "\t$PCF_NAME\t$Param_ID\t$OFFBYTE\t$OFFBIT\t$WIDTH\t$PCF_RELATED\t$PCF_DESCR \t${NumTMPara}" 
     packetligne="\t$PCF_NAME\t$Param_ID\t$OFFBYTE\t$OFFBIT\t$WIDTH\t$PCF_RELATED\t$PCF_DESCR" 
     done 

    #Why does NumTMPara = 0 ?? 
    echo -e "$PID_SPID\t$TPCF_NAME\t${NumTMPara}" 
    done 

一切都很好...

NCGT0030 14189 16 0 16 TC Packet ID 1 
NCGT0040 14190 18 0 16 TC Packet Seq Control 2 
NCGT0020 14188 20 0 16 Generic Failure ID 3 
NCGB00B4 14074 22 0 32 Data Field Header 4 

直到这个:

10512 YCSR271B 0 

为什么0?

+0

OMG,请修复格式。 – KurzedMetal 2012-07-23 18:17:17

+0

您不需要用分号替换标签:'cut -d $'\ t'-f2'将直接在标签上工作。 – chepner 2012-07-23 19:08:23

+0

@chepner:无论如何,标签是默认的分隔符,所以'cut -f2'就足够了。 – ruakh 2012-07-23 19:09:19

回答

3

问题是,在流水线(command1 | command2 | command3)中,每个命令都在单独的子shell中运行。这意味着主shell中的任何变量都被复制到每个命令的执行环境中,但是该命令所做的任何更改都不会被复制回主shell的执行环境中。

您有几种选择,但有两个主要的:

  • 你可以调整你的脚本,以便变量是被分配管线内部。
    • 例如,您可以编写while ... do ... done < <(command1 | command2)而不是command1 | command2 | while ... do ... done。这仍然会在子shell中运行command1command2,但while -loop将根据需要在主shell中运行。
  • 您可以将该变量保存到管道完成后您可以读取的临时文件中。
+0

它的工作原理!谢谢 !你知道我可以从哪里得到关于这个语法的信息吗? – user1546581 2012-07-24 08:08:55

+0

@ user1546581:'<(command)'符号被称为*进程替换*,并记录在* Bash参考手册的§3.5.6“进程替换”中(http://www.gnu.org) /software/bash/manual/bashref.html#Process-Substitution)。然而,我从来没有见过这样一个事实的文档,你可以写'<(command)'来从标准输入中取代替代进程的输出。我只知道它,因为我看到有人在StackOverflow的评论中提到过它。 – ruakh 2012-07-24 13:29:13