我试图使用整数来计算循环迭代次数,但循环完成后,变量为空。我用谷歌搜索过线索,但没有运气。
我有这个代码:
#!/bin/bash
declare -i count
echo entering loop
while read var
do
(( count++ ))
echo $count
done
echo exited loop
echo count is $count
当我以交互方式运行它时,输入“c”后按 Ctrl+D,我得到如下输出:
$ ./example
entering loop
a
1
b
2
c
3
exited loop
count is 3
但是当我将输入输入到循环中时:
#!/bin/bash
declare -i count
echo entering loop
ls -la | while read var
do
(( count++ ))
# do something interesting here
echo $count
done
echo exited loop
echo count is $count
...我得到这样的输出:
$ ./example
entering loop
1
2
3
4
5
exited loop
count is
$
为什么退出循环后不显示“count is 5”?
答案1
当您将值通过管道传输到 while 循环时,管道中的命令将在子 shell 中运行,并且当 while 循环结束时,计数器变量的值将丢失。
您可以通过使用来解决此行为流程替代而不是管道:
#!/bin/bash
declare -i count
while read var
do
((count++))
echo "$count"
done < <(ls -la)
echo "count is $count"
或者您可以启用该lastpipe
功能以bash
在当前 shell 上下文中运行管道的最后一个命令:
https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html
lastpipe
如果设置,并且作业控制未激活,shell 将运行当前 shell 环境中未在后台执行的管道的最后一个命令。
#!/bin/bash
declare -i count
shopt -s lastpipe # enable lastpipe
ls -la | while read var
do
((count++))
echo "$count"
done
shopt -u lastpipe # disable lastpipe
echo "count is $count"
有关的:
答案2
请参阅 BASH 手册的第 3.2.2 节:https://www.gnu.org/software/bash/manual/bash.html
由于每个管道都在单独的子 shell 中执行,因此管道命令中计数变量的更新超出了范围。
但是,您可以在shopt -s lastpipe
脚本开头使用主作用域来设置最终管道的执行。这将使计数变量更新进入与脚本的主 shell 相同的范围,从而能够恢复最终计数器值。