本文介绍了做'cat foo.txt |my_cmd'和'my_cmd<foo.txt"完成相同的操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题帮助我了解了重定向和管道之间的区别,但是示例着重于重定向STDOUT(echo foo> bar.txt )和管道STDIN( ls | grep foo ).

This question helped me understand the difference between redirection and piping, but the examples focus on redirecting STDOUT (echo foo > bar.txt) and piping STDIN (ls | grep foo).

在我看来,可以写为 my_command<file.txt 也可以写为 cat file.txt |my_command .在什么情况下需要STDIN重定向?

It would seem to me that any command that could be written my_command < file.txt could also be written cat file.txt | my_command. In what situations are STDIN redirection necessary?

除了使用 cat 会产生额外的过程而且效率不如重定向STDIN之外,您是否有必须使用STDIN重定向的情况?换句话说,是否有理由将 cat 的输出传递给另一个命令?

Apart from the fact that using cat spawns an extra process and is less efficient than redirecting STDIN, are there situations in which you have to use the STDIN redirection? Put another way, is there ever a reason to pipe the output of cat to another command?

推荐答案

my_command<有什么区别?file.txt cat file.txt |my_command ?

my_command < file.txt

重定向符号也可以写为 0< ,因为这会将文件描述符0( stdin )重定向为连接到 file.txt 当前设置的值,可能是终端.如果 my_command 是内置的Shell,则不会创建子进程,否则将创建一个子进程.

The redirection symbol can also be written as 0< as this redirects file descriptor 0 (stdin) to connect to file.txt instead of the current setting, which is probably the terminal. If my_command is a shell built-in then there are NO child processes created, otherwise there is one.

cat file.txt | my_command

这会将命令左侧的文件描述符1( stdout )重定向到匿名管道的输入流,并将命令的文件描述符0( stdin )重定向到在匿名管道输出流的右侧.

This redirects file descriptor 1 (stdout) of the command on the left to the input stream of an anonymous pipe, and file descriptor 0 (stdin) of the command on the right to the output stream of the anonymous pipe.

我们立即看到有一个子进程,因为 cat 不是内置的shell.但是,即使 my_command 是内置的shell,在 bash 中它仍将在子进程中运行.因此,我们有两个子进程.

We see at once that there is a child process, since cat is not a shell built-in. However in bash even if my_command is a shell builtin it is still run in a child process. Therefore we have TWO child processes.

因此,从理论上讲,管道效率较低.该差异是否显着取决于许多因素,包括显着"的定义.首选管道 的时间是这种替代方式:

So the pipe, in theory, is less efficient. Whether that difference is significant depends on many factors, including the definition of "significant". The time when a pipe is preferable is this alternative:

command1 > file.txt
command2 < file.txt

在这里很可能

command1 | command2

效率更高,请记住,在实践中,我们可能需要在 rm file.txt 中使用第三个子进程.

is more efficient, remembering that, in practice, we will probably need a third child process in rm file.txt.

但是,管道有局限性.它们不是可搜索的(随机访问,请参见 man 2 lseek ),并且不能进行内存映射(请参见 man 2 mmap ).某些应用程序将文件映射到虚拟内存,但是将其映射到 stdin stdout 并不常见.特别是在管道上(无论是匿名的还是命名的),内存映射都是不可能的,因为必须保留一定范围的虚拟地址,并且为此需要一个大小.

However, there are limitations to pipes. They are not seekable (random access, see man 2 lseek) and they cannot be memory mapped (see man 2 mmap). Some applications map files to virtual memory, but it would be unusual to do that to stdin or stdout. Memory mapping in particular is not possible on a pipe (whether anonymous or named) because a range of virtual addresses has to be reserved and for that a size is required.

如@JohnKugelman所述,一个常见的错误和许多SO问题的根源是与子进程和重定向相关的问题:

As mentioned by @JohnKugelman, a common error and source of many SO questions is the associated issue with a child process and redirection:

以99行作为文件 file.txt :

i=0
cat file.txt|while read
do
   (( i = i+1 ))
done

echo "$i"

显示什么?答案是 0 .为什么?因为计数 i = i + 1 是在 subshel​​l 中完成的,因此在 bash 中是子进程,不会更改i (注意:这不适用于korn shell ksh ).

What gets displayed? The answer is 0. Why? Because the count i = i + 1 is done in a subshell which, in bash, is a child process and does not change i in the parent (note: this does not apply to korn shell, ksh).

while read
do
   (( i = i+1 ))
done < file.txt

echo "$i"

这将显示正确的计数,因为不涉及任何子进程.

This displays the correct count because no child processes are involved.

这篇关于做'cat foo.txt |my_cmd'和'my_cmd&lt;foo.txt"完成相同的操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 17:27
查看更多