为什么无论是否启用“lastpipe”BASH_SUBSHELL它始终为 0?

Why BASH_SUBSHELL is always 0 no matter `lastpipe` is enabled or not?

提问人:matrixzj 提问时间:8/6/2023 最后编辑:Tom Solidmatrixzj 更新时间:8/7/2023 访问量:52

问:

我做了一些研究pipesubshell

多命令管道中的每个命令(用于创建管道)都在其自己的子 shell 中执行,该子 shell 是一个单独的进程(请参阅命令执行环境)。如果使用 shopt builtin 启用了 lastpipe 选项(请参阅 Shopt Builtin),则当作业控制未处于活动状态时,管道的最后一个元素可能由 shell 进程运行。

测试代码

#!/bin/bash


set +m

shopt -u lastpipe
shopt | grep lastpipe

function test() {
  echo "This is first pipe"  | echo $BASH_SUBSHELL
}

test

shopt -s lastpipe
shopt | grep lastpipe

function test() {
  echo "This is first pipe"  | echo $BASH_SUBSHELL
}

test

输出为

lastpipe        off
0
lastpipe        on
0

预期结果是

lastpipe        off
1
lastpipe        on
0
bash 子壳

评论


答:

3赞 larsks 8/6/2023 #1

您的问题是在管道运行之前执行变量替换。当你写的时候:

echo "This is first pipe"  | echo $BASH_SUBSHELL

在运行管道之前,会在当前 shell 中展开。为了正确地执行测试,您需要将语句放在一个函数中以延迟替换:$BASH_SUBSHELLecho

test_subshell() {
  echo $BASH_SUBSHELL
}

然后你会看到不同的行为:

$ test_subshell
0
$ echo "This is first pipe" | test_subshell
1

评论

0赞 KamilCuk 8/7/2023
我不同意。BASH_SUBSHELL在子 shell 中展开。
0赞 larsks 8/7/2023
我很高兴接受我的答案不正确的想法,但您不能只是告诉我们这是错误的,您能提供更新的答案吗?为什么显示与 ?echo foo | echo $BASH_SUBSHELLecho foo | test_subshell
0赞 KamilCuk 8/7/2023
是的,所以我无法回答,所以我想在我能证明不是这样之前,你可以忽略我。能证明吗?或?我尝试阅读文档,但我认为在代币化后何时发生扩展是 100% 清楚的。export BASH_SUBSHELL; echo | env | grep BASH_SUBSHELLecho | { echo $BASH_SUBSHELL; }
1赞 larsks 8/7/2023
我一直认为整个流水线的变量替换发生在流水线执行之前......例如,bash 手册页说,“扩展是在命令行被拆分为单词后执行的”,我认为这意味着“在执行任何事情之前”。
0赞 KamilCuk 8/7/2023
例如,返回两个不同的 pid。echo $BASHPID; echo | echo $BASHPID