使用“|”来自 Bash 的 if 构造阻止设置变量
Using '|' from Bash's if construct prevents variable being set
我了解到您可以将 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"
运行 Bash 64 位 Linux 版本 4.3.11 产生以下输出:
VAR_0: Unmodified
VAR_1: Changed
请注意,唯一的区别是我如何从 if 结构中重定向标准输出。为什么是“|”防止 VAR_0 被更改?
发生这种情况是因为管道使用子外壳;通过管道连接到 cat
,您已经使第一个 if-then 块在子 shell 中执行。因此,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;因此该变量仍然存在。
TL;DR
查看 Bash FAQ 24。
它回答了您的问题并提供了示例!
您正在创建一个 SubShell,它又连同父 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"
输出:
var value inside subshell is: 1
But in the parent shell it stays: 0
当不需要这种行为时,解决方案通常是使用进程替换 来保持变量更新。因此,在我们的例子中(或者在 Bash FAQ 24 中通常可以看到)我们执行以下操作:
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
我了解到您可以将 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"
运行 Bash 64 位 Linux 版本 4.3.11 产生以下输出:
VAR_0: Unmodified
VAR_1: Changed
请注意,唯一的区别是我如何从 if 结构中重定向标准输出。为什么是“|”防止 VAR_0 被更改?
发生这种情况是因为管道使用子外壳;通过管道连接到 cat
,您已经使第一个 if-then 块在子 shell 中执行。因此,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;因此该变量仍然存在。
TL;DR
查看 Bash FAQ 24。 它回答了您的问题并提供了示例!
您正在创建一个 SubShell,它又连同父 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"
输出:
var value inside subshell is: 1
But in the parent shell it stays: 0
当不需要这种行为时,解决方案通常是使用进程替换 来保持变量更新。因此,在我们的例子中(或者在 Bash FAQ 24 中通常可以看到)我们执行以下操作:
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