使用' |'如果构造阻止变量被设置,则来自Bash' s

时间:2016-03-21 21:45:54

标签: bash if-statement pipe pipeline

我已经读过您可以将I / O重定向到Bash中的各种结构(例如"如果"和#34;而#34;)。当我尝试这个时,我注意到使用" |"在if结构的末尾,阻止了我在if结构中覆盖的任何变量生效;但如果我使用">"相反,变量修改生效。

#!/bin/bash

VAR_0='Unmodified'

if true
then
    VAR_0='Changed'
fi | cat

echo "VAR_0: $VAR_0"

###########

VAR_1='Unmodified'

if true
then
    VAR_1='Changed'
fi > tmpFile
rm tmpFile

echo "VAR_1: $VAR_1"

在64位Linux上运行Bash版本4.3.11会产生以下输出:

VAR_0: Unmodified
VAR_1: Changed

注意唯一的区别是我如何从if结构重定向stdout。为什么" |"阻止VAR_0被改变?

2 个答案:

答案 0 :(得分:1)

TL; DR

结帐Bash FAQ 24。 它会回答您的问题以及提供的示例!

您正在创建一个SubShell,而Process Substitution将与其父变量的副本一起被丢弃。

以下面的常见错误为例:

var=0
some-command | while read -r line; do
    printf 'var value inside subshell is: %s\n' "$((++var))"
done
printf 'But in the parent shell it stays: %s\n' "$var"

输出:

var value inside subshell is: 1
But in the parent shell it stays: 0

当不希望这种行为时,解决方案通常是使用Bash FAQ 24来更新变量。因此,在我们的情况下(或通常在{{3}}中可以看到),我们执行以下操作:

var=0
while read -r line; do
    printf 'var value inside subshell is: %s\n' "$((++var))"
done < <(some-command)
printf 'And it stays the same: %s\n' "$var"

输出:

var value inside subshell is: 1
And it stays the same: 1

答案 1 :(得分:0)

这是因为管道使用子壳;通过管道到cat,你已经在子shell中执行了第一个if-then块。因此,VAR_0='Changed'已更改,但仅在子shell中。

尝试:

#!/bin/bash

VAR_0='Unmodified'

if true
then
    VAR_0='Changed'
    echo "VAR_0: $VAR_0"
fi | cat

echo "VAR_0: $VAR_0"

重定向到文件(“>”)创建子shell;因此该变量仍然存在。