在很多答案中,主要是关于text-processing
命令,我看到诸如sed
、awk
、grep
等命令与 STDIN 一起使用以及简单地打开文件
例如
$ sed -e 's|foo|bar|g' file # open file
$ sed -e 's|foo|bar|g' <file # open STDIN
或者
$ grep 'PATTERN' file # open file
$ grep 'PATTERN' <file # open STDIN
就个人而言,我总是使用打开文件方法,但我想知道何时和何时不使用它们,以及有什么区别。
答案1
这取决于需要。在这种情况下,使用文件名或来自标准输入的管道会产生影响。
bash-4.1$ cat /etc/passwd /etc/group | wc -l
128
bash-4.1$ wc -l /etc/passwd /etc/group
49 /etc/passwd
79 /etc/group
128 total
bash-4.1$
此外,标准输入往往不是很lseek(3)
强大,因此如果应用程序需要一个可以查找的文件描述符(例如倒回到开头),则可能会排除使用标准输入的可能性。
答案2
就输出而言,没有什么区别。
$ grep 'PATTERN' file
将打开参数 2 中指定的文件并搜索模式。
$ grep 'PATTERN' <file
file
将读取into的内容STDIN
(bash 的功能之一),并将通过管道传输STDIN
到grep
.
我不确定其中之一是否有确切的好处,但我会继续使用前者而不是后者。
后者是多余的,就像cat file | grep 'PATTERN'
和cat file | sed -e 's|foo|bar|g'
是多余的一样。
答案3
在某些情况下,两者并不完全相同,例如:
$ wc -l ./script.sh
4948 ./script.sh
$ wc -l <./so
4948
首先wc
知道正在处理哪个文件并打印文件名和行数。在第二个中,该命令wc
不知道正在处理什么文件,它是匿名输入。
在使用 grep 的示例的特定命令中:
$ grep 'PATTERN' file
$ grep 'PATTERN' <file
输出没有区别。但有了这个,就有了(如果有匹配的话):
$ grep -H 'PATTERN' file
$ grep -H 'PATTERN' <file
此外,在重定向的情况下<file
,shell 正在读取文件,这也可能对缓冲的速度或大小(对于不同的命令)产生影响。
答案4
区别主要在于谁打开文件。这可能很重要安全原因-- shell 可能具有启动的程序所没有的特权。
使用 STDIN 方法意味着将流继承到由启动的程序创建的整个进程树。这在某些情况下可能很有用。
随着打开文件方法,启动的程序更容易知道文件名。采用文件名路由的程序可能会在其输出中使用文件名,并且文件名路由可能在其他方面有所不同,例如性能:程序通常假设仅对 STDIN 进行基本流访问(无查找,无映射性)以及文件名参数的可查找性。