以下代码是实际任务的简化版本。当然,我知道我可以用 来实现此简化示例中所做的事情if [ ... ]
。这只是为了演示令人惊讶的行为:
# /bin/bash
CURRD=dir1
IS_THIS=N
DATALINES=dir1
echo $DATALINES | while read DLINE
do
echo IS_THIS1 ${IS_THIS}
if [ "$DLINE" != "$CURRD" ]
then
echo $DLINE is not current dir
else
echo $DLINE is current dir
IS_THIS=Y
echo IS_THIS2 ${IS_THIS}
fi
done
echo IS_THIS3 ${IS_THIS}
我希望得到这个输出:
IS_THIS1 N
dir1 is current dir
IS_THIS2 Y
IS_THIS3 Y
但我得到的是:
IS_THIS1 N
dir1 is current dir
IS_THIS2 Y
IS_THIS3 N
因此,在循环内部,变量IS_THIS
被设置为Y
。我期望它在循环外部保持该值。但显然情况并非如此。它会返回到循环外部的值。这就好像 -loop 内部的代码是一个带有局部变量的空间。我对这里的 shell 脚本while
有什么不理解的?bash
我在 bash 3.2.51(1) 和 bash 4.1.11(2) 中尝试过此操作。两者都显示相同的行为。
PS:由于我无法用循环解决实际任务while read
,我将换行符设置处的输入拆分IFS
为换行符,并使用括号中的输入初始化数组变量,然后for
对数组变量的元素进行循环。所以任务解决了,我只是好奇想知道while read
我对 bash 脚本中的循环有什么误解。
答案1
循环作为单独的进程运行,因此循环内的变量在循环结束时被销毁。
如果您可以使用 Python,它确实会在循环内保留变量的变化。
currd = ["dir1"]
is_this = "n"
datalines = ["dir1"]
print is_this # checking variable
for lines in datalines:
if lines != "".join(currd):
print lines + " is not current dir"
else:
print lines + " is current dir"
is_this = "y"
print is_this # checking if variable changed
答案2
上面的评论中给出了这个答案10b0是正确的。我本来想将其标记为正确答案,但这是一条评论,所以我不能:
USE 上有很多重复项,但很难找到。例如在各个循环中附加到同一个数组,只保留最后的值 Bash 4
那里给出了两种解决方案。对我来说,实际上只有使用 Here-document 的那个才有效。为了更容易找到答案,下面是我上面的示例代码,按照 USE 中的建议使用 Here-document 完成的。它避免了管道,因此避免了循环的子 shell,因此变量IS_THIS
是相同的,并且值的设置被保留:
# /bin/bash
CURRD=dir1
IS_THIS=N
DATALINES=dir1
while read DLINE
do
echo IS_THIS1 ${IS_THIS}
if [ "$DLINE" != "$CURRD" ]
then
echo $DLINE is not current dir
else
echo $DLINE is current dir
IS_THIS=Y
echo IS_THIS2 ${IS_THIS}
fi
done <<< "$DATALINES"
echo IS_THIS3 ${IS_THIS}