Bash 为什么一个变量在一个循环内改变,而在循环外没有改变
我在读取val时使用Bash 为什么一个变量在一个循环内改变,而在循环外没有改变,bash,Bash,我在读取val时使用命令| awk'{print$1;}';执行循环执行命令输出。最近我想计算总和,我在bash中发现了一些奇怪的行为: test.txt的内容 100 200 300 测试内容。sh sum='0' cat test.txt | awk '{ print $1; }' | while read val ; do sum=`expr $sum + $val` echo "sum is now: $sum" done echo "FINAL SU
命令| awk'{print$1;}';执行
循环执行命令输出。最近我想计算总和,我在bash
中发现了一些奇怪的行为:
test.txt的内容
100
200
300
测试内容。sh
sum='0'
cat test.txt | awk '{ print $1; }' | while read val ; do
sum=`expr $sum + $val`
echo "sum is now: $sum"
done
echo "FINAL SUM: $sum"
sum is now: 100
sum is now: 300
sum is now: 600
FINAL SUM: 0
执行test.sh的输出
sum='0'
cat test.txt | awk '{ print $1; }' | while read val ; do
sum=`expr $sum + $val`
echo "sum is now: $sum"
done
echo "FINAL SUM: $sum"
sum is now: 100
sum is now: 300
sum is now: 600
FINAL SUM: 0
最后的总数应该是600。我能做些什么来修复此问题?原因是使用了
cat
,这会产生另一个子shell。这意味着sum
变量在第二个子shell中递增,然后在循环完成时超出范围(并返回到其先前的值0
)
尝试更新循环以不使用cat
:
sum='0'
while read val ; do
sum=`expr $sum + $val`
echo "sum is now: $sum"
done < test.txt
echo "FINAL SUM: $sum"
sum='0'
while read val ; do
sum=`expr $sum + $val`
echo "sum is now: $sum"
done < <(cat test.txt | awk '{ print $1 }')
echo "FINAL SUM: $sum"
原因是使用了
cat
,这会产生另一个子shell。这意味着sum
变量在第二个子shell中递增,然后在循环完成时超出范围(并返回到其先前的值0
)
尝试更新循环以不使用cat
:
sum='0'
while read val ; do
sum=`expr $sum + $val`
echo "sum is now: $sum"
done < test.txt
echo "FINAL SUM: $sum"
sum='0'
while read val ; do
sum=`expr $sum + $val`
echo "sum is now: $sum"
done < <(cat test.txt | awk '{ print $1 }')
echo "FINAL SUM: $sum"
没有必要使用bash管道。您可以使用
awk
:
awk '{sum+= $1; printf "The sum is now: %s\n", sum } END { print "FINAL SUM:", sum }' file.txt
结果:
The sum is now: 100
The sum is now: 300
The sum is now: 600
FINAL SUM: 600
没有必要使用bash管道。您可以使用
awk
:
awk '{sum+= $1; printf "The sum is now: %s\n", sum } END { print "FINAL SUM:", sum }' file.txt
结果:
The sum is now: 100
The sum is now: 300
The sum is now: 600
FINAL SUM: 600
要扩展NewFurniture所述内容,但您可以将其与任意输入命令一起使用,而不仅仅是
cat
:
sum='0'
while read val ; do
sum=`expr $sum + $val`
echo "sum is now: $sum"
done < test.txt
echo "FINAL SUM: $sum"
sum='0'
while read val ; do
sum=`expr $sum + $val`
echo "sum is now: $sum"
done < <(cat test.txt | awk '{ print $1 }')
echo "FINAL SUM: $sum"
sum='0'
读val时;做
sum=`expr$sum+$val`
echo“总和现在是:$sum”
完成<以扩展NewFurniture的状态,但您可以将其与任意输入命令一起使用,而不仅仅是cat
:
sum='0'
while read val ; do
sum=`expr $sum + $val`
echo "sum is now: $sum"
done < test.txt
echo "FINAL SUM: $sum"
sum='0'
while read val ; do
sum=`expr $sum + $val`
echo "sum is now: $sum"
done < <(cat test.txt | awk '{ print $1 }')
echo "FINAL SUM: $sum"
sum='0'
读val时;做
sum=`expr$sum+$val`
echo“总和现在是:$sum”
done<这种奇怪的行为实际上是由bash管道引起的
引用
管道中的每个命令都在其自己的子shell中执行
将sum
视为while循环中的局部变量,这就是为什么退出while循环时,sum
似乎没有设置的原因
其他人提出的解决方案可以正常工作。这种奇怪的行为实际上是由bash管道引起的
引用
管道中的每个命令都在其自己的子shell中执行
将sum
视为while循环中的局部变量,这就是为什么退出while循环时,sum
似乎没有设置的原因
其他人提出的解决方案可以很好地工作。OP希望使用awk预处理输入,为此,您可以使用done<@imp25替换while循环的结束行。示例文件的内容仅包含一列-因此awk'{print$1}'
是多余的;然而,我更新的答案允许在不需要循环的情况下充分利用它(考虑到OP在循环中不需要任何额外的处理)。我只是用cat来说明我的问题OP希望用awk预处理输入,要做到这一点,您可以用done<@imp25替换while循环的结束行。示例文件的内容只包含一列-因此awk'{print$1}'
是多余的;然而,我更新的答案允许在不需要循环的情况下充分利用它(考虑到OP在循环中不需要任何额外的处理)。我只是用猫来说明我的问题。管道是一个强大的工具,不了解管道的人不能使用。但是,每个人都应该使用Awk。:)+1.管道是一个强大的工具,不了解管道的人不能使用。但是,每个人都应该使用Awk。:)+1.我只想补充一点,关于这里发生的事情的文档在标题为“.+1”的章节中。我只想补充一点,关于这里发生的事情的文档在标题为“”的一节中。