A variable modified inside a while loop is not remembered

后端 未结 8 2149
挽巷
挽巷 2020-11-21 05:06

In the following program, if I set the variable $foo to the value 1 inside the first if statement, it works in the sense that its value is remember

8条回答
  •  被撕碎了的回忆
    2020-11-21 05:13

    This is an interesting question and touches on a very basic concept in Bourne shell and subshell. Here I provide a solution that is different from the previous solutions by doing some kind of filtering. I will give an example that may be useful in real life. This is a fragment for checking that downloaded files conform to a known checksum. The checksum file look like the following (Showing just 3 lines):

    49174 36326 dna_align_feature.txt.gz
    54757     1 dna.txt.gz
    55409  9971 exon_transcript.txt.gz
    

    The shell script:

    #!/bin/sh
    
    .....
    
    failcnt=0 # this variable is only valid in the parent shell
    #variable xx captures all the outputs from the while loop
    xx=$(cat ${checkfile} | while read -r line; do
        num1=$(echo $line | awk '{print $1}')
        num2=$(echo $line | awk '{print $2}')
        fname=$(echo $line | awk '{print $3}')
        if [ -f "$fname" ]; then
            res=$(sum $fname)
            filegood=$(sum $fname | awk -v na=$num1 -v nb=$num2 -v fn=$fname '{ if (na == $1 && nb == $2) { print "TRUE"; } else { print "FALSE"; }}')
            if [ "$filegood" = "FALSE" ]; then
                failcnt=$(expr $failcnt + 1) # only in subshell
                echo "$fname BAD $failcnt"
            fi
        fi
    done | tail -1) # I am only interested in the final result
    # you can capture a whole bunch of texts and do further filtering
    failcnt=${xx#* BAD } # I am only interested in the number
    # this variable is in the parent shell
    echo failcnt $failcnt
    if [ $failcnt -gt 0 ]; then
        echo $failcnt files failed
    else
        echo download successful
    fi
    

    The parent and subshell communicate through the echo command. You can pick some easy to parse text for the parent shell. This method does not break your normal way of thinking, just that you have to do some post processing. You can use grep, sed, awk, and more for doing so.

提交回复
热议问题