Об'єднайте кілька команд unix в один вихід


9

Мені потрібно шукати в наших журналах електронної пошти певну адресу електронної пошти. Ми зберігаємо поточний файл з іменем maillog , а також файли .bz2 на тиждень у тій же папці. На даний момент я виконую наступні команди для пошуку файлу:

grep person@domain.com maillog
bzgrep person@domain.com *.bz2

Чи є спосіб об'єднати команди grepта bzgrepкоманди в один вихід? Таким чином, я можу передавати об'єднані результати в один електронний лист або в один файл.

Відповіді:


24

Інший спосіб

{ grep ...; bzgrep ...;} >file

&&має труднощі, що bzgrepне буде запущено, якщо grepне вдалося.

Зверніть увагу на обов'язковий пробіл після відкриття фігурної дужки та крапки з комою після останньої команди. Крім того, ви можете використовувати синтаксис нижньої оболонки (круглі дужки замість фігурних дужок), що не так вибагливо:

(grep ...; bzgrep ...) >file

+1 за найкращий загальний підхід до цього питання. Групування оболонок - це, як правило, недостатньо використана функція.
Філ Холленбек

2
Ви не маєте на увазі ()замість цього {}?
Ехтеш Чудхурі

Для арки linux це працювало, ()але ні {}, в будь-якому випадку +1, оскільки це те, що мені потрібно!
Кріс Магнусон

11

bzgrep автоматично встановлюється за замовчуванням на звичайний grep, якщо файл не стискається bzip. Таким чином, повинно бути достатньо наступного:

bzgrep person@domain.com maillog *bz2 | mail -s "logs yay" someuser@blah

о, звичайно, ось і моє обов'язкове рішення GNU Paralellel :

parallel -m bzgrep person@domain.com ::: maillog* *bz2 | mail -s "logs yay" someuser@blah

що може бути набагато швидше, якщо ви перевіряєте багато файлів.


2

Ось ще один спосіб зробити це (якщо припустити, що ви використовуєте баш, який ви, мабуть, є):

cat <(bzgrep ...) <(grep ...)

Тут bash прозоро подає вихід команд bzgrep та grep в cat, як ніби вони були файлами (і вони начебто знаходяться під кришкою, деталі в URL-адресі внизу).

У вашому конкретному випадку я б рекомендував рішення Філа, але вищезгадане - хороший трюк, який слід тримати в сумці.

Якщо вас цікавить, ви можете прочитати більше тут: http://www.tldp.org/LDP/abs/html/process-sub.html


Ага так, канонічна відповідь "як ви відрізняєте вихід двох процесів". Хороший трюк, щоб знати.
Філ Холленбек

1

На момент написання цього моменту синтаксис прийнятої відповіді був неправильним для більшості, якщо не всіх оболонок, отриманих Борном, в тому числі bash. Я запропонував редагувати вгорі і прийняв відповідь, щоб виправити це, але я також схильний був додати всю цю іншу інформацію, і це було б більше переписати замість редагування.

Ви можете використовувати складені команди:

{ grep ...; bzgrep ...; } >file

.. або додаткові оболонки (зверніть увагу на дужки замість фігурних дужок):

(grep ...; bzgrep ...) >file

..групувати команди. Спосіб допоміжної оболонки має приємніший синтаксис (більше прощає відсутність пробілу та дозволяє опустити останню крапку з комою), але він або видобуває новий процес, або "робить вигляд", виконуючи команди в очищеному середовищі. Обидва мають переваги залежно від того, що ви хочете зробити, але тут не важливо, але варто шукати, якщо ви хочете більше володіти оболонкою.

Примітка: Ви також можете використовувати конвеєрне з'єднання з цими хитрощами, щоб ви могли зробити щось подібне:

{ grep ...; bzgrep ...; } | less

PS якщо ви не дбаєте про впорядкування матчів у вашій сукупної продукції, ви можете використовувати один &між двома командами, наприклад , так: { grep ... & bzgrep ...; }. Потім дві команди запускаються одночасно: grepзапускається і оболонка ставить її на задній план, тоді оболонка запустить bzgrep. (Але тут є невеликий застереження, тому що пояснення включають перенаправлення файлів та буферизацію потоку файлів, що потенційно може спричинити розбиття / змішування дуже невеликої частини рядків у вихідному файлі: чи бачите ви, що це залежатиме від того, як ваш grep, bzgrep, і libc stdio.hфункції реалізовані. У більшості реалізацій, я вважаю, що прошивка команди перед перенаправленням у файл дозволить уникнути проблеми, тож ви можете зробити це { foo & bar; } | cat - >fileяк вирішення.)


0

Ви можете зв'язати команди разом із &&, що дозволить виконувати кожну команду.

ви також можете додати >> textfile.txt до кінця кожної команди та мати вихід у відповідь на файл, а потім надіслати пошту.


2
Як згадував geekosaur, && тут не слід використовувати, оскільки повернене значення grep залежить від того, знайшов він щось чи ні. Якщо ви зробили це grep ... && bzgrep ..., якщо у грепа не було хітів, він поверне провал, і команда припиниться. >>Хороша ідея, проте, на відміну від цього >, вона додасть вихід до кінця наявного файлу.
DerfK

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