我看到这样的表达式command1 | {command2;command3;command4}
,我在想这实际上意味着什么,我知道管道符号,我知道{...}
强制运行主 shell 中大括号内的命令,但我很困惑它们的组合含义。
答案1
管道的各个部分有多复杂并不重要,如果需要,您通常可以将它们可视化为单独的脚本(特别是在像这样bash
无论如何都会在子 shell 中运行管道的每个部分的 shell 中)。
剧本
command2
command3
command4
... 哪个大致是{ command2; command3; command4; }
翻译成的(不考虑{ ...; }
名义上意味着命令不在子shell中运行),是从执行中给出的输入
command1
根据第一个脚本中的这三个命令正在执行的操作,其中一个或多个命令可能会消耗来自 的输入command1
,并且如果其中一个或多个命令产生任何输出,则该输出将进入管道的下一部分,或者终端或管道输出重定向到的任何地方。
答案2
{...}
强制运行主 shell 中大括号内的命令
这并不能很好地描述大括号的一般作用。以不创建子 shell 的方式将命令括起来。换句话说,大括号本身并不创建子 shell:大括号中的代码在同一个 shell 中执行,就好像没有大括号一样,而不是括号中的代码始终在子 shell 中执行(因此它的重定向、变量、等等不影响父 shell 或任何其他 shell)。
大括号的目的是允许在语法需要单个命令的情况下编写复杂的命令。例如,在command1 | { command2; command3; command4; }
(请注意空格和最后的分号是必需的)中,管道的右侧是{ command2; command3; command4; }
。该命令{ command2; command3; command4; }
执行command2
,然后command3
,然后command4
。所有这些命令都从管道获取输入。 (由于命令连续运行,command3
因此获取运行后留下的任何输入command2
,依此类推。)
答案3
将大括号视为未命名的函数。例如
command234 () { command2; command3; command4; }
command1 | command234
给出相同的结果。当事情变得太复杂时,我更喜欢命名分组。如果只是为了测试。
答案4
标准输出command1
将用于命令块中的第一个命令,该命令开始从标准输入读取。在大多数情况下,这将是command2
。