Когда я должен использовать перенаправление ввода?


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

Может ли кто-нибудь объяснить мне любые плюсы / минусы, если какой-либо из этих двух подходов друг к другу.

Ответы:


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открывает файл; во втором случае оболочка открывает файл и присваивает его стандартному вводу 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и администраторы должны знать об этом лучше).


+1, за хорошее объяснение. У меня есть одно сомнение: во 2-м случае, когда оболочка открывает файл, она передает содержимое открытого файла на стандартный ввод (клавиатура)? (Я запутался с термином «стандартный ввод grep»).
Ankit

1
@Ankit, stdin - это место, где приложения по умолчанию читают свои данные, дескриптор файла 0. Когда в терминале fd 0 открывается для чтения на терминальном устройстве (что-то вроде / dev / ttyxx или / dev / pts / n). Вот так они и получают то, что вы печатаете на клавиатуре. Перенаправление оболочки стандартного ввода команды просто открывает fd 0 для другого файла перед выполнением команды.
Стефан Шазелас

6

Ответ 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; между оболочкой, выполняющей файл frobbing ( ), и командой, выполняющей ее самостоятельно, может быть небольшая разница во времени <, но, вероятно, это незаметно, если вы не делаете ничего в течение всего дня. Это будет зависеть от таких факторов, как плюсы, упомянутые в ответе Стефана.


cmd fileне короче чем cmd<fileхотя бы.
Стефан Шазелас

Это на одно нажатие клавиши короче, при условии, что вам нужно нажать Shift, чтобы набрать a <.
DopeGhoti
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.