Bash:在 while 循环中增加变量?

Bash:在 while 循环中增加变量?

我有一个 bash 脚本,对于一组中的每个文件,greps 文件中的每一行以查找字符串。然后,它用逗号分割该行,将第 7 个元素转换为浮点数,并按该值递增运行总计。

它看起来像这样:

for filename in data*.CSV; do
   echo $filename
   ACTUAL_COST=0
   grep '040302010' $filename | while read -r line ; do
       IFS=',' read -a array <<< "$line"
       ACTUAL_COST=$(echo "$ACTUAL_COST + ${array[7]}" | bc)
       echo $ACTUAL_COST
   done
   echo $ACTUAL_COST
done

但我遇到的问题是这会产生如下输出:

53.4
72.2
109.1
0

最后一个值始终为 0。谷歌搜索了一下后,我认为这是因为循环while在子 shell 中执行,因此外部变量没有更改。

我知道我可能需要执行函数中的内部循环。

答案1

这不是你编写 shell 脚本的方式。您正在为文件的每一行按顺序运行多个命令!

在这里你想要类似的东西:

awk -F, '/040302010/ {actual_cost += $7}
         ENDFILE {print FILENAME ":", +actual_cost; actual_cost=0}
        ' data*.CSV

(假设 GNU awk)。

那是所有文件的命令总数。

答案2

为了避免使用子 shell,您可以使用以下命令:

while read -r line
do
    your_stuff
done < <(grep '040302010' $filename')

这样您就可以将结果填充到变量中。

答案3

引入另一个命令替换可能会很方便,其中核心循环逻辑在函数中定义:

sum_cost() {
   sum=0
   while read -r line ; do
       IFS=',' read -a array <<< "$line"
       sum=$(echo "$sum + ${array[7]}" | bc)
   done
   echo $sum
}

for filename in data*.CSV; do
   echo $filename
   ACTUAL_COST=$(grep '040302010' $filename | sum_cost)
   echo $ACTUAL_COST
done

相关内容