Со 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открывает файл; во втором случае оболочка открывает файл и присваивает его стандартному вводу grep, и, grepне передавая ни одного аргумента имени файла, предполагает, что ему необходим grep для стандартного ввода.
Плюсы 1:
grep может grep больше чем один файл¹.
grepможет отображать имя файла, где находится каждое вхождение line.
Плюсы 2:
- Если файл не может быть открыт, оболочка возвращает ошибку, которая будет включать в себя более важную информацию (например, номер строки в скрипте) и более согласованным образом (если вы разрешите оболочке открывать файлы и для других команд), чем когда
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
С точки зрения производительности, если файл не может быть открыт, вы сохраняете выполнение grepпри использовании перенаправления, но в остальном grepя не ожидаю большой разницы.
С перенаправлением вы избавляете от необходимости передавать дополнительный аргумент grep, вы grepнемного облегчаете анализ аргументов. С другой стороны, оболочке потребуется (как минимум) дополнительный системный вызов 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утилиты) и, следовательно, менее эффективно, может вызвать путаницу, если первый файл не заканчивается символом новой строки и не сообщит вам, в каком файле находится шаблон.
² В случае ksh93и, тем не bashменее, существуют такие файлы, как /dev/tcp/host/port(и /dev/fd/xв некоторых системах bash), которые при использовании в качестве цели перенаправления перехватывает оболочку для специальных целей, вместо того, чтобы действительно открывать файл в файловой системе (хотя обычно эти файлы не существует в файловой системе). /dev/stdinслужит для той же цели, что и -распознаваемый grep, но, по крайней мере, здесь он более правильно расположен в пространстве имен (любой может создать файл с именем -в любом каталоге, в то время как только администраторы могут создать файл с именем, /dev/tcp/host/portи администраторы должны знать об этом лучше).