当我运行以下Bash脚本时,我希望它能够打印出来Hello.相反,它打印一个空行并退出.
echo 'Hello' | echo
Run Code Online (Sandbox Code Playgroud)
为什么不piping从输出echo到echo工作?
iob*_*der 56
echo打印所有参数.它不读取stdin.所以第二个echo打印所有参数(无)并退出,忽略Helloon stdin.
对于读取stdin并打印它的程序stdout,使用cat:
$ echo Hello | cat
Hello
Run Code Online (Sandbox Code Playgroud)
cda*_*rke 16
你好像不懂管道.在这种情况下,它们更准确地称为匿名管道,因为它们没有名称(也有命名管道).匿名管道仅在相关进程之间工作,例如具有相同父进程的进程.
管道是由C运行时库产生的IO系统的一部分.默认情况下,这些流是缓冲的(有一个例外).基本上,管道只是将输出缓冲区从一个进程连接到另一个进程的输入缓冲区.
使用的前三个流(称为文件描述符)编号为0,1和2.第一个,0,称为标准输入,或stdin(C中使用的名称).默认情况下,它连接到键盘,但可以使用<符号或程序名称位于管道右侧来重定向.
第二个,称为 标准输出,或stdout.默认情况下,它连接到终端屏幕,但可以使用>管道左侧的符号或程序名称重定向.
所以:
echo 'Hello' | echo
Run Code Online (Sandbox Code Playgroud)
获取标准输出echo并将其传递给标准输入echo.但是echo不读stdin!没有任何反应.
筛选程序处理命令行中指定的文件名.如果没有给出文件名,那么他们会读取标准输入.示例包括cat,, grep和sed,但不是 echo.例如:
echo 'Hello' | cat
Run Code Online (Sandbox Code Playgroud)
将显示"你好",这cat是无用的(通常是).
echo 'Hello' | cat file1
Run Code Online (Sandbox Code Playgroud)
将忽略输出echo,只显示file1的内容.请记住,只有在没有给出文件名的情况下才会读取stdin.
你觉得这显示了什么?
echo 'Hello' | cat < file1 file2
Run Code Online (Sandbox Code Playgroud)
为什么?
最后,第三个流2称为标准错误,或者stderr,这个是无缓冲的.它被管道忽略,因为它们只在stdin和stdout之间运行.但是,您可以重定向stderr以使用stdout(请参阅参考资料man dup2):
myprog 2>&1 | anotherprog
Run Code Online (Sandbox Code Playgroud)
的2>&1手段"文件描述符2重定向到相同的位置FIE描述符1".
以上是正常行为,但程序可以覆盖所有这些,如果它想要.例如,它可以从文件描述符2中读取.我省略了很多其他细节,包括其他形式的重定向,例如进程替换和这里的文档.
这是因为echo(内置和/bin/echo)不从 中读取任何内容stdin。
改用cat:
echo 'Hello' | cat
Hello
Run Code Online (Sandbox Code Playgroud)
或者没有管道:
cat <<< 'Hello'
Run Code Online (Sandbox Code Playgroud)
只能对从stdin输入命令的管道进行配管。但是回声并不来自标准输入。它将从参数获取输入并进行打印。所以这行不通。为了回声,您可以做类似的事情echo $(echo 'hello')