有人可以解释为什么这个脚本没有产生我期望的输出吗?
#!/bin/bash
#
var=0
ls -1 /tmp| while read file
do
echo $file
var=1
done
echo "var is $var"
我得到一个文件列表,然后是var is 0
为什么 var 不等于 1?是因为 while 循环产生了一个子 shell 吗?
答案1
管道确实如此。您可以自己检查,例如通过$BASHPID
从 while 循环的内部和外部打印或执行以下操作:
ls | while read file; do
sleep 100;
done
,停止它C-Z
并检查ps
或ps --forest
之后查看终端会话中的进程树。
您可以通过稍微不同的“管道”来避免子 shell:
var=0
while read file
do
echo $file; var=1
done < <(ls -1 /tmp/)
echo $var #=> 1
答案2
其他好的答案已经解释了不保留变量值的原因。如果您愿意,可以阅读有关此主题的有趣文章我在管道中的循环中设置变量。为什么循环结束后它们就消失了?或者,为什么我无法通过管道读取数据?。
我只是想展示另一种循环文件的方法,这样您就ls
根本不需要解析:
for file in /tmp/*
do
echo "$file"
var=1
done
就是这样!只需让/tmp/*
Expand 即可提供目录中的所有内容/tmp
。
我猜你的脚本只是一些虚拟代码,而不是真正的代码。但如果你碰巧要检查是否/tmp
包含某些值,你也可以说:
shopt -s nullglob
r=(/tmp/*)
然后计算数组中的元素:
echo ${#r[@]}
请注意,如果没有任何内容与此模式匹配,我过去常常shopt -s nullblog
阻止/tmp/*
扩展到文字字符串。/tmp/*
答案3
while
不会,但管道会,因此while
您的示例中的 将会在子 shell 中运行
人们通常可以使用循环来完成相同的任务for
,其中生成要迭代的列表的命令在子 shell 中运行,而不是在循环中运行。例如:
for file in /tmp/*; do
echo "$file"
var=1
done