管道和输入流重定向到同一命令,命令采用哪个输入?

管道和输入流重定向到同一命令,命令采用哪个输入?

我试图运行下面给出的命令

cat numbers.txt | sort < words.txt

上面的命令有一个从 cat 命令馈送到 sort 命令输入流的管道。但同时,sort命令的输入流也被重定向到words.txt文件。运行命令时,我发现words.txt 中的数据已按排序命令排序并显示回终端中。

我不明白在这种情况下外壳程序如何处理管道和重定向。一个命令是否可以接受来自两个不同源的输入流。我对其内部工作方式的想法是,由于重定向和管道是沿着命令从左到右处理的,因此首先将 cat 命令的输出流作为 sort 命令的输入流。但由于排序命令在该管道之后提供了另一个输入流重定向,因此排序命令的输入流将连接到words.txt。因此,当命令执行时,words.txt 中的数据只会到达排序命令。

另外为什么下面的命令不运行。我已经通过覆盖更改了重定向,通过附加重定向。

cat numbers.txt | sort << words.txt

有一个问题部分与此类似,但我无法完全理解外壳程序如何处理管道和重定向。

答案1

重定向是从左到右处理的,并且在 Bash 中,在管道之后(事实上​​,在任何 POSIX shell)。在

cat numbers.txt | sort < words.txt

shell 首先将sort的(未来)标准输入设置为来自 的管道cat,但随后在处理时< words.txt将其更改为读取words.txt

<<启动一个定界符:

cat numbers.txt | sort << words.txt

将等待一行显示“words.txt”(因为这是命令中指定为输入结束标记)。请参阅shell 的控制和重定向运算符是什么?

答案2

一个命令是否可以接受来自两个不同源的输入流。

不;输入流实际上只是其他人交给您的文件描述符。正如一个文件中只有一个文件一样,无法合并多个流。

cat numbers.txt | sort < words.txt

顺便说一句,cat是 con enate 的缩写cat;从字面上看,它的工作是将命令行上指定的所有文件连接到其输出流:

cat numbers.txt words.txt | sort 

作品。当然,sort它本身也可以对多个文件进行排序,所以sort numbers.txt words.txt效果也一样。

但我想这个问题更普遍:
如果我有多个文件和流,如何将它们连接成一个输出?

嗯,现代 shell 确实可以满足您的需求(至少 bash 和 zsh 可以):

cat file1 <(some program that generates output) <(echo "foo bar") file2 | sort

这些 shell 具有<(…),即“生成一个作为输入文件名传递的临时管道”。当然,还有非常简单的子shell方法:

( cat file1; some program that generates output; echo "foo bar"; cat file2 ) | sort

具有相同的效果。 (那里执行并行度的差异;cat <(sleep 2; echo hello) <(sleep 2; echo world)总共需要2秒执行;(sleep 2; echo hello; sleep 2; echo world)需要 4 秒。)

相关内容