为什么变量即使应该改变也没有改变?

为什么变量即使应该改变也没有改变?

我有这个 bash 脚本:

#!/bin/bash

someVar=0

tac /etc/hosts | while IFS= read line; do
    echo "$someVar : $line"
    someVar=$((someVar+1))
done
echo "Finally: $someVar"

当我使用 运行它时./test.sh,我得到以下输出:

0 : ::1             localhost ipv6-localhost ipv6-loopback
1 : fe00::0         ipv6-localnet
2 : ff00::0         ipv6-mcastprefix
Finally: 0

为什么 varsomeVar末尾是 0,即使之前是 2,即使如上所述这里它应该是全局的,并且在 var 增加之前就执行得很好?

答案1

为什么 var someVar 末尾是 0?

ShellCheck – shell脚本分析工具有答案:

someVar 的修改是局部的(由管道导致的子外壳程序)。

$ shellcheck myscript
 
Line 5:
tac /etc/hosts | while IFS= read line; do
                            ^-- SC2162 (info): read without -r will mangle backslashes.
 
Line 7:
    someVar=$((someVar+1))
    ^-- SC2030 (info): Modification of someVar is local (to subshell caused by pipeline).
 
Line 9:
echo "Finally: $someVar"
               ^-- SC2031 (info): someVar was modified in a subshell. That change might be lost.

$ 

答案2

我找到了答案。

我们不用创建子 shell |,而是可以在最后注入它。它无法与基本一起使用< $(cmd),但可以< <(cmd)正常工作。

最终的脚本是这样的:

#!/bin/bash

someVar=0

while IFS= read line; do
    echo "$someVar : $line"
    someVar=$((someVar+1))
done < <(tac /etc/hosts) # <---- changes here
echo "Finally: $someVar"

输出:

0 : ::1             localhost ipv6-localhost ipv6-loopback
1 : fe00::0         ipv6-localnet
2 : ff00::0         ipv6-mcastprefix
Finally: 3 # not 0 !

相关内容