据我了解,管道( | )
将一个进程的标准输出作为标准输入传递到另一个进程。
但我想知道管道是否( | )
被视为像 ls、grep 等这样的命令。
下面的命令行有多少个命令?
ls /etc | grep nginx
我很困惑是否应该计算管道( | )
答案1
在 Bash 中,管道(|
以及|&
)不是命令,而是控制运算符。
从此引用:
管道是由控制运算符“|”或“|&”分隔的一个或多个命令的序列。
因此,在您的示例上下文中,ls
和grep
将是命令,并且您不应该包含管道。
答案2
实际测试才是证明。在 bash 中:
|
返回:
-bash:意外标记‘|’附近有语法错误
尽管:
a|b
其中 a 和 b 是未知命令,返回:
-bash:b:未找到命令 -bash:a:未找到命令
没有引用 | 因为管道在任意两个命令之间使用时完全没问题,问题是这些命令不存在。
我怀疑“b:命令未找到”先出现,因为按顺序接收方 (b) 必须在发送方 (a) 之前运行。如果它们先启动 (a),然后启动 (b),如果 (b) 启动所花的时间比 (a) 开始发送所花的时间长,数据将无处可去。
答案3
补充另一个答案:管道运算符告诉 shell 这两个命令应该组织在管道中,就像文本从一个命令流向另一个命令一样。为此,shell 通过调用内核创建一个匿名管道,即一个类似 FIFO 文件的通道。然后 shell 运行这两个命令,将管道的输入作为其 stdout 文件描述符传递给第一个命令,将管道的输出作为其 stdin 传递给第二个命令。因此,文本通过管道从第一个命令的 stdout 传输到第二个命令的 stdin。
如果管道符号表示一个单独的命令,则该程序需要以某种方式获取其他两个命令的进程,然后将匿名管道的文件描述符传递给它们(假设这在非父子进程之间是可能的),并且这些程序在运行时需要用这些描述符交换它们的 stdout 和 stdin — 在此期间可能会丢失输出。这一切由 shell 更容易完成,因为它已经知道这两个进程,与它们具有特殊的父关系,并且可以在开始时提供文件描述符。