【问题标题】:variable reset in a bash script在 bash 脚本中重置变量
【发布时间】:2011-11-10 21:13:52
【问题描述】:

一个简单的变量测试:

#!/bin/bash

N=0

ls -l | while read L; do
 N=$((N+1))
 echo $N
done

echo "total $N"

运行然后输出:

1
2
3

total 0

我期望最终 N=3:“total 3”,但为什么循环后值重置为 0?

【问题讨论】:

标签: bash


【解决方案1】:

bash 在其自己的子 shell 中的管道中运行每个语句。 (对于ls 等外部命令,子shell 只需execs 命令。)这有效地使所有变量都本地化。您通常必须通过使用重定向或命令替换而不是管道来解决此问题。

编辑:这似乎有效:

#!/bin/bash
IFS=
N=0

while read L; do
  N=$((N+1))
  echo $N
done <<<$(ls -l)

echo "total $N"

编辑:从 bash 4.2 开始,您可以在脚本中使用 shopt -s lastpipe 来禁用管道中最后一个命令的子 shell,然后允许其余原始代码按需要工作。

【讨论】:

  • 重定向背后的逻辑是什么?为什么它会阻止 while 循环脱壳?
  • @olimpiabaku 实际上是管道使 bash 成为 while 循环的子外壳,尽管从 bash 4.2 开始,您可以在脚本中禁用它(请参阅我的编辑)。