Bash:使用tee的for循环中变量的范围

俄罗斯方块11

考虑:

numbers="1 111 5 23 56 211 63"
max=0

for num in ${numbers[@]}; do

      [ $num -gt $max ]\
           && echo "old -> new max = $max -> $num"\
           && max=$num

done | tee logfile

echo "Max= $max"

如果我删除| tee logfile了max变量,则正确地将其打印为211,但是如果我将其保留在其中,则会得到Max= 0

到底是怎么回事?

吉勒斯“别再邪恶了”

管道的每一面都在子外壳中执行。子外壳程序是原始外壳程序流程的副本,该流程以相同的状态开始,然后独立地发展¹。子外壳程序中设置的变量无法转回到父外壳程序。

在bash中,您可以使用流程替换来代替管道除了循环在原始外壳中tee执行并且仅在子外壳中执行之外,这与管道的行为几乎相同

for num in "${numbers[@]}"; do
  if ((num > max)); then
    echo "old -> new max = $max -> $num"
    max=$num
  fi
done > >(tee logfile)
echo "Max= $max"

在执行此操作时,我更改了脚本中的一些内容:

请注意,管道解决方案和子shell解决方案之间的差异很小:管道命令在两个命令都退出时完成,而带有进程替换的命令在主命令退出时完成,而无需等待进程替换。这意味着当您的脚本完成时,日志文件可能未完全写入。

另一种方法是使用其他通道从子Shell到原始Shell进程进行通信。您可以使用一个临时文件(灵活但难做—将临时文件写入适当的目录,避免名称冲突(使用mktemp),即使出现错误也将其删除)。或者,您可以使用另一个管道来传递结果,并通过命令替换来获取结果。

max=$({ { for … done;
          echo "$max" >&4
        } | tee logfile >&3; } 4>&1) 3&>1

的输出tee转到文件描述符3,该文件描述符3重定向到脚本的标准输出。的输出echo "$max"转到文件描述符4,该文件描述符4重定向到命令替换中。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章