2

入力ファイルからの数値の束を一時ファイルにロードしたい。スクリプトの形式は「testing -row/-col [入力ファイル]」です。入力ファイルは、ほとんどの場合、次のような乱数の集まりです

1 2 3 4
3 3 5 6
9 4 4 2

以下の私のコードは、この入力ファイルを引数として取得し、これらの数値を新しい一時ファイルに "cat" しようとしています。そこから、この一時ファイルから行の平均値を見つけようとしています。

FILENAME=$2
TMP=./TMP2.$$
cat $FILENAME > $TMP

#average row 
function avg_row {
while read -a row  
do
    total=0
    sum=0
    for i in "${rows[@]}"
    do
         eum=`expr $sum + $i`
         total=`expr $total + 1`
    done
    average=`expr $sum / $total`
    echo $average
done < $TMP
}

ただし、TMPファイルを「cat」するとtesting_fileとまったく同じように表示されますが、スクリプトを実行すると印刷されます

 expr: division by zero
 expr: division by zero
 expr: division by zero

なぜこれが起こるのかについての提案やアイデアはありますか? ありがとうございました。

4

1 に答える 1

1

2 つの問題:

  1. 関数は配列を読み取りrowますが、存在しない配列にアクセスしようとしますrowsrowsにはエントリtotalがなく、インクリメントされることはなく、除算はゼロ除算であるためです。

  2. eumではなく、この行が更新されますsum

    eum=`expr $sum + $i`
    

また、$FILENAME の内容が読み取られる前にコピーされる理由も明確ではありません。これには正当な理由があると思います。

修正された関数は次のようになります。

function avg_row {
while read -a row  
do
    total=0
    sum=0
    for i in "${row[@]}"
    do
         sum=`expr $sum + $i`
         total=`expr $total + 1`
    done
    average=`expr $sum / $total`
    echo $average
done < $TMP

これにより、次の出力が生成されます。

$ avg_row
2
4
4

現代化された bash バージョン

バックティックと は両方ともexpr古風です。関数のより最新の bash バージョンは次のとおりです。

avg_row2() {
while read -a row
do
    sum=0
    for i in "${row[@]}"
    do
        ((sum += i))
    done
    echo $((sum / ${#row[@]}))
done < $TMP
}

これにより、前と同じ出力が生成されます。

$ avg_row2
2
4
4

awk バージョン

awk でも同じことができます。

$ awk '{s=0; for (i=1;i<=NF;i++) s+=$i; print int(s/NF);}' filename
2
4
4

bash とは異なり、awk は浮動小数点演算を実行できます。

$ awk '{s=0; for (i=1;i<=NF;i++) s+=$i; print s/NF;}' filename
2.5
4.25
4.75
于 2015-10-07T05:36:31.120 に答える