使用'|';来自Bash';s if构造阻止设置变量

使用'|';来自Bash';s if构造阻止设置变量,bash,if-statement,pipe,pipeline,Bash,If Statement,Pipe,Pipeline,我已经读到,您可以将I/O重定向到Bash中的各种构造中或从中重定向出来(例如“if”和“while”)。当我尝试这一点时,我注意到在if构造的末尾使用“|”会阻止我在if构造中过度编写的任何变量生效;但是如果我使用“>”,那么变量修改就会生效 #!/bin/bash VAR_0='Unmodified' if true then VAR_0='Changed' fi | cat echo "VAR_0: $VAR_0" ########### VAR_1='Unmodifie

我已经读到,您可以将I/O重定向到Bash中的各种构造中或从中重定向出来(例如“if”和“while”)。当我尝试这一点时,我注意到在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被更改?

这是因为管道使用子shell;通过管道传输到
cat
,您已经在子shell中执行了第一个if-then块。因此,
VAR\u 0='Changed'
被更改,但仅在子shell中更改

尝试:

重定向到文件(“
”)不会创建子shell;因此,该变量持续存在。

TL;博士 退房。 它与提供的示例一起回答您的问题


您正在创建一个脚本,该脚本将与其父shell的变量副本一起丢弃

以以下常见错误为例:

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"
输出:

当不需要这个behvior时,通常使用解决方案来更新变量。因此,在我们的情况下(或从中可以普遍看出),我们做了以下工作:

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
But in the parent shell it stays: 0
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