从子shell设置父shell的变量

Mat*_*ner 42 bash shell subshell

如何在子shell中设置父shell中的变量?

a=3
(a=4)
echo $a
Run Code Online (Sandbox Code Playgroud)

cda*_*rke 47

子shell的重点是它不会影响调用会话.在bash中,子shell是子进程,其他shell有所不同,但即使这样,子shell中的变量设置也不会影响调用者.根据定义.

你需要一个子壳吗?如果你只需要一个组,那么使用大括号:

a=3
{ a=4;}
echo $a
Run Code Online (Sandbox Code Playgroud)

给出4(小心那个空间).或者,将变量值写入stdout并在调用者中捕获它:

a=3
a=$(a=4;echo $a)
echo $a
Run Code Online (Sandbox Code Playgroud)

避免使用反向标记``,它们被弃用并且难以阅读.


Ben*_*ela 33

有gdb-bash-variable hack:

gdb --batch-silent -ex "attach $$" -ex 'set bind_variable("a", "4", 0)'; 
Run Code Online (Sandbox Code Playgroud)

虽然这总是在全局范围内设置一个变量,而不仅仅是父范围

  • +1真棒.-1纯粹的恐怖. (41认同)
  • 虽然不那么危险,但我会说这应该像实际剧本中的叉炸弹一样频繁使用. (18认同)

rua*_*akh 22

你没有.子shell无法访问其父级环境.(至少在Bash提供的抽象中.你可能会尝试使用gdb,或粉碎堆栈等等,以秘密获取此类访问权限.但我不建议这样做.)

另一种方法是子shell将赋值语句写入临时文件,以便其父级读取:

a=3
(echo 'a=4' > tmp)
. tmp
rm tmp
echo "$a"
Run Code Online (Sandbox Code Playgroud)

  • 如果你使用子shell来收集父shell稍后需要的多个变量的值,那么文件方法非常有用,特别是在_not_使用子shell是非常重要的情况下. (2认同)

mar*_*ark 12

如果问题与while循环有关,解决此问题的一种方法是使用Process Substitution:

    var=0
    while read i;
    do
      # perform computations on $i
      ((var++))
    done < <(find . -type f -name "*.bin" -maxdepth 1)
Run Code Online (Sandbox Code Playgroud)

如下所示:https://stackoverflow.com/a/13727116/2547445


Ict*_*tus 11

通过阅读@ruakh (谢谢)使用临时文件方法的答案以及要求文件描述符解决方案的评论,我得到了以下想法:

a=3    
. <(echo a=4; echo b=5)
echo $a
echo $b
Run Code Online (Sandbox Code Playgroud)
  • 它允许一次返回不同的变量(这可能是接受答案的子 shell 变体中的问题)。
  • 不需要迭代,
  • 无需处理临时文件。
  • 接近OP提出的语法。

结果:

4
5
Run Code Online (Sandbox Code Playgroud)

启用 xtrace 后,可以看到我们正在从为子 shell 的输出创建的文件描述符中获取数据:

+ a=3
+ . /dev/fd/63 # <-- the file descriptor ;)
++ echo a=4
++ echo b=5
++ a=4
++ b=5
+ echo 4
4
+ echo 5
5
Run Code Online (Sandbox Code Playgroud)


Car*_*sch 7

要更改从父脚本调用的脚本中的变量,可以调用前面带有"."的脚本.

a=3
echo $a    
. ./calledScript.sh
echo $a
Run Code Online (Sandbox Code Playgroud)

在calledScript.sh中

a=4
Run Code Online (Sandbox Code Playgroud)

预期产出

3
4
Run Code Online (Sandbox Code Playgroud)

  • 在当前的shell中运行`namedScript.sh`,因此它不属于“ subshel​​l”。 (2认同)

cia*_*mej 7

不要从父 shell 访问变量,而是更改命令的顺序并使用进程替换

a=3
echo 5 | (read a)
echo $a
Run Code Online (Sandbox Code Playgroud)

打印 3

a=3
read a < <(echo 5)
echo $a
Run Code Online (Sandbox Code Playgroud)

打印 5

另一个例子:

let i=0 
seq $RANDOM | while read r
              do 
                let i=r 
              done
echo $i
Run Code Online (Sandbox Code Playgroud)

let i=0
while read r 
do 
  let i=r 
done < <(seq $RANDOM)
echo $i
Run Code Online (Sandbox Code Playgroud)

或者,当作业控制处于非活动状态时(例如在脚本中),您可以使用lastpipeshell 选项来实现相同的结果,而无需更改命令的顺序:

#!/bin/bash
shopt -s lastpipe
let i=0
seq $RANDOM | while read r
              do 
                let i=r
              done
echo $i
Run Code Online (Sandbox Code Playgroud)