Bash
脚本时,我期望它会输出 Hello
。但事实上,它只会输出空白行并退出。echo 'Hello' | echo
为什么从echo
输出到echo
的piping
不起作用?
echo
命令打印其所有参数,不会从stdin
读取信息。因此,第二个echo
会打印其所有参数(没有),然后退出,忽略stdin
上的Hello
。
如果要编写一个程序来读取stdin
并将其输出到stdout
,请使用cat
命令:
$ echo Hello | cat
Hello
$ echo Hello | xargs echo
默认情况下等同于 echo Hello | xargs
。 - daGo在这种情况下,您使用的管道更正确地被称为匿名管道,因为它们没有名称(还有命名管道)。匿名管道只能在相关进程之间工作,例如具有相同父级的进程。
管道是C运行时库产生的IO系统的一部分。默认情况下,这些缓冲流(有一个例外)会被缓存。基本上,管道只是将一个进程的输出缓冲区连接到另一个进程的输入缓冲区。
使用的前三个流(称为文件描述符)的编号为0、1和2。第一个,0,称为标准输入或stdin
(在C中使用的名称)。默认情况下,这与键盘连接,但可以通过使用<
符号或程序名位于管道右侧来重定向它。
第二个,1,称为标准输出或stdout
。默认情况下,这与终端屏幕连接,但可以通过使用>
符号或程序名位于管道左侧来重定向。
因此:
echo 'Hello' | echo
将echo
的标准输出传递给echo
的标准输入。但是echo
不会读取stdin!所以什么都不会发生。
筛选程序处理在命令行上指定的文件名。如果没有指定文件名,则它们会读取stdin。示例包括cat
、grep
和sed
,但不包括echo
。例如:
echo 'Hello' | cat
将显示“Hello”,而cat
是无用的(通常情况下是这样)。
echo 'Hello' | cat file1
将echo
的输出忽略,仅显示file1文件的内容。请记住,只有在没有给出文件名时才会读取标准输入。
你认为这会显示什么?
echo 'Hello' | cat < file1 file2
为什么?
最后,第三个流2称为标准错误,或者stderr
,它是未缓冲的。 它被管道忽略,因为它们只在stdin和stdout之间操作。 但是,您可以重定向stderr以使用stdout(请参见 man dup2
):
myprog 2>&1 | anotherprog
2>&1
的意思是“将文件描述符 2 重定向到与文件描述符 1 相同的位置”。
尽管如此,程序可以覆盖所有这些行为。例如,它可以从文件描述符 2 中读取。我省略了很多其他详细信息,包括其他形式的重定向,如进程替换和Here 文档。
管道只能用于以stdin作为输入的命令。但是echo不从stdin中获取输入。它将从参数获取输入并输出。因此,这种方法行不通。要使用echo,可以尝试如下方法:echo $(echo 'hello')
这是因为echo
(包括内置的和/bin/echo
)不从stdin
读取任何内容。
可以使用cat
代替:
echo 'Hello' | cat
Hello
或者不使用管道符:
cat <<< 'Hello'