【问题标题】:Using '|' from Bash's if construct prevents variable being set [duplicate]使用“|”来自 Bash 的 if 构造阻止设置变量 [重复]
【发布时间】:2023-03-16 19:46:01
【问题描述】:

我了解到您可以将 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 被更改?

【问题讨论】:

    标签: bash if-statement pipe pipeline


    【解决方案1】:

    TL;DR

    查看Bash FAQ 24。 它连同提供的示例一起回答了您的问题!


    您正在创建一个SubShell,而该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
    

    当不需要这种行为时,解决方案通常是使用Process Substitution 来保持变量更新。因此,在我们的例子中(或者在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
    

    【讨论】:

      【解决方案2】:

      这是因为管道使用子外壳;通过管道到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"
      

      重定向到一个文件(“&gt;”)不会创建一个子shell;因此该变量仍然存在。

      【讨论】:

        猜你喜欢
        • 2021-12-28
        • 1970-01-01
        • 2018-10-24
        • 2019-02-22
        • 1970-01-01
        • 2016-08-02
        • 2018-04-29
        • 1970-01-01
        相关资源
        最近更新 更多