在对另一篇文章的评论中,@ JonathanLeffler表示:
{...} | somecommand在子shell中运行,不会影响父shell.演示:
man bash
(输出PQR,ABC,PQR三行)
确实:
X=PQR; echo $X; { X=ABC; echo $X; } | cat; echo $X
Run Code Online (Sandbox Code Playgroud)
但是,{ .. }说man bash不会在子shell中执行:
james@bodacious-wired:tmp$X=PQR; echo $X; { X=ABC; echo $X; } | cat; echo $X
PQR
ABC
PQR
Run Code Online (Sandbox Code Playgroud)
那么这里发生了什么?是echo $$错?我知道管道的每个部分都在子shell中执行; 但我不知道这是如何导致观察到的行为.例如:
{ list; }
list is simply executed in the current shell environment. list must be
terminated with a newline or semicolon. This is known as a group command.
Run Code Online (Sandbox Code Playgroud)
编辑添加:
一些人建议$$用来表明事物是(或不是)子壳的一部分.这根本没有用,因为ps在参数扩展阶段会扩展,这在任何命令执行之前很久就会发生.
举个例子:
james@bodacious-wired:tmp$X=PQR; echo $X | sed; X=ABC; echo $X | sed; echo $X
PQR
ABC
ABC
Run Code Online (Sandbox Code Playgroud)
你可以看到第二次调用7894发生在子shell中,带有pid echo 2$$; 但{ .. }仍然显示bash在变量扩展阶段中替换的值,在它生成子shell之前
为了对比,并表明man bash它没有产卵子shell:
james@bodacious-wired:tmp$echo 1$$; ps; ( echo 2$$; ps ); echo 3$$; ps
11194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
21194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
7894 ttys000 0:00.00 -bash
31194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
james@bodacious-wired:tmp$
Run Code Online (Sandbox Code Playgroud)
只是为了证明@nos是正确的,在上面添加一个管道:
james@bodacious-wired:tmp$echo 1$$; ps; { echo 2$$; ps; }; echo 3$$; ps
11194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
21194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
31194
PID TTY TIME CMD
1194 ttys000 0:00.23 -bash
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,shell产生两个子壳,一个用于管道的每一侧.
管道的每一侧至少成为子壳.
{ X=ABC; echo $X; }
将制作一个子壳/过程,至少cat和echo $X.
"管道中的每个命令都作为一个单独的进程执行(即,在子shell中)." ,来自man bash
如果你改为这样做
{ X=SUB ; sleep 1; } &
之后你会看到{ X=SUB ; sleep 1; }显示ABC.
还有其他方法可以在子shell中执行命令,例如,如果你背景子命令:(X=ABC ; echo $X),该组将在子shell中运行,而{ X=ABC; echo $X; }不会.
如果要对始终在子shell中执行的命令进行分组,请使用括号cat而不是大括号.
| 归档时间: |
|
| 查看次数: |
2369 次 |
| 最近记录: |