什么时候应该使用输入重定向?

Ank*_*kit 21 io-redirection

我使用以下两个命令来产生相同的结果:-

[root@localhost ~]# grep line comments
The line should start with a single quote to comment in VB scripting.
Double slashes in the beginning of the line for single line comment in C.
[root@localhost ~]#

[root@localhost ~]# grep line <comments
The line should start with a single quote to comment in VB scripting.
Double slashes in the beginning of the line for single line comment in C.
[root@localhost ~]#
Run Code Online (Sandbox Code Playgroud)

如果这两种方法中的任何一种相互替代,请向我解释任何优点/缺点。

Sté*_*las 29

man grep页面(在 Debian 上):

描述

   grep  searches the named input FILEs (or standard input if no files are
   named, or if a single hyphen-minus (-) is given as file name) for lines
   containing  a  match to the given PATTERN.  By default, grep prints the
   matching lines.
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,grep打开文件;在第二个中,shell 打开文件并将其分配给 的标准输入grep,并且grep没有传递任何文件名参数假定它需要 grep 其标准输入。

优点1:

  • grep 可以 grep 多个文件¹。
  • grep可以显示line找到每个出现的文件名。
  • grepcan²(但我不知道有任何实现)fadvise(POSIX_FADV_SEQUENTIAL)在它打开的文件描述符上做一个。

优点2:

  • 如果无法打开文件,shell 将返回一个错误,其中包含更多相关信息(如脚本中的行号),并且以更一致的方式(如果您让 shell 也为其他命令打开文件)grep打开它。如果文件无法打开,grep甚至不会被调用(对于某些命令——也许不是grep——可能会有很大的不同)。

  • in grep line < in > out,如果in无法打开,out则不会被创建或截断。

  • 某些名称不寻常的文件(例如-或以-)³开头的文件名没有问题。

  • 化妆品:您可以<file在命令行的任何位置放置以更自然地显示命令流,就像<in grep line >out您喜欢的那样。

  • 化妆品:使用 GNU grep,您可以选择在匹配行前面使用的标签,而不仅仅是文件名,如下所示:

     <file grep --label='Found in file at line' -Hn line
    
    Run Code Online (Sandbox Code Playgroud)

在性能方面,如果文件打不开,你保存grep使用重定向时的执行,否则grep我不期望有太大的区别。

使用重定向,您无需将额外的参数传递给grep,从而使grep的参数解析稍微容易一些。另一方面,shell 将需要(至少)对dup2()文件描述符 0 上的文件描述符进行额外的系统调用。

{ grep -m1 line; next command; } < file, grep(此处为 GNU grep)将要seek()返回到匹配行之后,以便next command查看文件的其余部分(它还需要确定文件是否可查找)。换句话说, stdin 中的位置是 的另一个grep输出。使用grep -m1 line file,它可以优化它,这是grep需要关心的少一件事。


笔记

¹ 使用zsh,您可以:

grep line < file1 < file2
Run Code Online (Sandbox Code Playgroud)

但这相当于cat file1 file2 | grep line(不调用cat实用程序),因此效率较低,如果第一个文件不以换行符结尾,并且不会让您知道在哪个文件中找到该模式,则会引起混淆。

² 即告诉系统grep将要按顺序读取文件,以便 I/O 调度程序可以做出更明智的决定,例如如何读取数据。grep可以在它自己的fd 上这样做,但是在它从调用者那里借来的fd 0 上这样做是错误的,因为该 fd(或者更确切地说它引用的打开文件描述)可以稍后甚至同时使用用于非顺序读取。

³在的情况下,ksh93bash虽然有像文件 /dev/tcp/host/port(并/dev/fd/x在某些系统bash),在重定向的目标使用时,特殊用途,而不是真正打开文件系统上的文件外壳拦截(虽然一般,这些文件文件系统上不存在)。/dev/stdin-识别的目的相同grep,但至少,这里的命名空间更合适(任何人都可以-在任何目录中创建一个名为的文件,而只有管理员可以创建一个名为的文件/dev/tcp/host/port,管理员应该更清楚)。


von*_*and 6

StephaneChazelas 的回答涵盖了grep(1)大多数 Unix 沿袭命令,但不是全部。从标准输入(从键盘,从通过 重定向的文件< file,或从另一个命令通过管道传输的输出,愚蠢的例子ls * | grep '^ab*c$')或从作为参数给出的文件(如grep comment file1 file2 file3. 一些命令在那里使用约定,命名的文件-是标准输入,所以你可以说make-middle | cat head - tail获取一个流head,无论gen-middle生成什么,然后是tail. 这是设计使然,以提供使用命令的灵活性。

哪个更好?只要它有效,cmd file就比cmd < file; 外壳程序执行文件 frobbing ( ) 和命令自己执行文件之间的时间可能存在微小差异<,但除非您整天无所事事,否则可能不会引起注意。这将取决于 Stephane 的回答中提到的专业人士等考虑因素。