在“while read”循环中设置的变量值在循环外丢失

在“while read”循环中设置的变量值在循环外丢失

以下代码是实际任务的简化版本。当然,我知道我可以用 来实现此简化示例中所做的事情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}

相关内容