我使用以下两个命令产生相同的结果:-
[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; } < file
,grep
(此处为 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 ( <
) 和命令本身执行此操作之间的时间差异,但可能不会被注意到,除非您整天不做任何其他事情。这将取决于斯蒂芬的回答中提到的优点等考虑因素。