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


21

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

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

如果这两种方法中的任何一种相互对立,请告诉我任何利弊。

Answers:


28

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可以显示每次line找到的文件名。

优点2:

  • 如果无法打开文件,则外壳程序将返回一个错误,该错误将包含比以下情况更相关的信息(如脚本中的行号),并且以更一致的方式(如果您也让外壳程序为其他命令打开文件)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实用程序),因此效率较低,如果第一个文件未以换行符结尾并且不会让您知道在哪个文件中找到了模式,则可能引起混乱。

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


+1,以获得很好的解释。我有一个疑问:在第二种情况下,当外壳程序打开文件时,它将打开的文件内容传递给标准输入(键盘)吗?(我对“ grep的标准输入”一词感到困惑)。
Ankit 2013年

1
@ Ankit,stdin是应用程序在默认情况下读取其输入的文件描述符0。在终端中,从终端设备上的读取(类似于/ dev / ttyxx或/ dev / pts / n)打开fd 0。这就是他们最终得到您在键盘上键入的内容的方式。在执行命令之前,命令的stdin的Shell重定向只会将fd 0打开到其他文件。
斯特凡Chazelas

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)回答中提到的专业人士之类的考虑。


cmd file不短于cmd<file
斯特凡Chazelas

不过,这只是短了一个按键,假设您需要按Shift才能输入a <
DopeGhoti
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.