Коли я повинен використовувати переадресацію вводу?


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

Чи не могли б мені пояснити будь-які плюси чи мінуси, якщо будь-який із цих 2 підходів один до одного.

Відповіді:


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не передається жоден аргумент імені файлу, передбачає, що йому потрібно зібрати його стандартний вхід.

Плюси 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аналіз аргументів трохи простіше. З іншого боку, оболонці знадобиться (принаймні) додатковий системний виклик 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").
Анкіт

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

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


cmd fileне коротше, cmd<fileхоча.
Стефан Шазелас

Хоча це один натискання клавіші коротше, припускаючи, що вам потрібно натиснути Shift для введення <.
DopeGhoti
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.