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

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

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

[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 ~]#

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

答案1

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.

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

1的优点:

  • grep可以 grep 多个文件1。
  • grep可以显示每次出现 的文件名line
  • grep可以²(但我不知道有任何实现)fadvise(POSIX_FADV_SEQUENTIAL)在它打开的文件描述符上执行 a 操作。

2的优点:

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

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

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

  • 修饰:如果您愿意,您可以将其放在<file命令行上的任何位置,以更自然地显示命令流程。<in grep line >out

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

     <file grep --label='Found in file at line' -Hn line
    

在性能方面,如果文件无法打开,则可以保存grep使用重定向时的执行,但除此之外,grep我预计不会有太大差异。

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

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


笔记

借助zsh,您可以执行以下操作:

grep line < file1 < file2

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

² 即告诉系统grep将按顺序读取文件,以便 I/O 调度程序可以做出更明智的决策,例如如何读取数据。grep可以在其上做到这一点自己的fd,但在 fd 0 上执行此操作是错误的借用来自它的调用者,就像那个 fd (或者更确切地说打开文件描述它引用)可以稍后甚至同时用于非顺序读取。但在实践中,您会注意到 GNUsort仍然这样做。

ksh93³ 在和的情况下bash,存在类似的文件 /dev/tcp/host/port(以及/dev/fd/x在 中的某些系统上bash),当在重定向目标中使用时,shell 会出于特殊目的而拦截这些文件,而不是真正打开文件系统上的文件(尽管通常这些文件文件系统上不存在)。与所识别的/dev/stdin目的相同,但至少,这里它的命名空间更合适(任何人都可以在任何目录中创建一个名为 的文件,而只有管理员可以创建一个名为 的文件,管理员应该更了解)。-grep-/dev/tcp/host/port

答案2

StephaneChazelas 的答案涵盖了grep(1),并且大多数 Unix lineage 命令都是这样工作的,但不是全部。标准的读取方式是从标准输入(从键盘,从通过 重定向的文件< file,或从另一个命令通过管道传输的输出,愚蠢的例子ls * | grep '^ab*c$'),或从作为参数给出的文件(如 )读取grep comment file1 file2 file3。某些命令使用约定,即命名的文件-是标准输入,因此您可以说make-middle | cat head - tail获取带有 的流head,无论gen-middle生成什么,后跟tail.这是设计使然,目的是为了让命令的使用更加灵活。

哪个更好?只要它有效,cmd file就比 短cmd < file;可能有一个微小的shell 执行文件 frobbing ( <) 和命令本身执行此操作之间的时间差异,但可能不会被注意到,除非您整天不做任何其他事情。这将取决于斯蒂芬的回答中提到的优点等考虑因素。

相关内容