Назад | Перейти на главную страницу

Объедините несколько команд unix в один вывод

Мне нужно найти в наших журналах почты определенный адрес электронной почты. Мы сохраняем текущий файл с именем почтовый журнал а также недельные файлы .bz2 в той же папке. В настоящее время я выполняю следующие команды для поиска файла:

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

Есть ли способ объединить grep и bzgrep команды в один выход? Таким образом, я мог передать объединенные результаты в одно электронное письмо или в один файл.

Другой способ

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

&& имеет трудность, что bzgrep не будет запущен, если grep не смогли.

Обратите внимание на обязательный пробел после открывающей фигурной скобки и точку с запятой после последней команды. В качестве альтернативы вы можете использовать синтаксис подоболочки (круглые скобки вместо фигурных скобок), который не так разборчив:

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

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

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

о, также, конечно, вот мой обязательный GNU Parallel решение тоже:

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

что может быть намного быстрее, если вы проверяете много файлов.

Вот еще один способ сделать это (при условии, что вы используете bash, что, вероятно, и есть):

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

Здесь bash прозрачно передает вывод команд bzgrep и grep в cat, как если бы они были файлами (и они вроде как под капотом, подробности в URL-адресе внизу).

В вашем конкретном случае я бы порекомендовал решение Фила, но приведенное выше - хороший трюк, чтобы держать его в сумке.

Если вам интересно, вы можете прочитать здесь: http://www.tldp.org/LDP/abs/html/process-sub.html

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

Вы можете использовать составные команды:

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

..или подоболочки (обратите внимание на круглые скобки вместо фигурных скобок):

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

..сгруппировать команды. Способ подоболочки имеет более приятный синтаксис (более снисходительный к отсутствию пробелов и позволяет опускать последнюю точку с запятой), но он либо вызывает новый процесс, либо «притворяется», выполняя команды в очищенной среде. У обоих есть преимущества в зависимости от того, что вы хотите сделать, которые здесь не имеют значения, но стоит поискать, если вы хотите более эффективно работать с оболочкой.

Примечание: вы также можете использовать конвейерную обработку с этими трюками, поэтому вы можете сделать что-то вроде этого:

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

P.S. если вам не важен порядок совпадений в комбинированном выводе, вы можете использовать один & между двумя командами, например: { grep ... & bzgrep ...; }. Затем две команды выполняются одновременно: grep запускается, и оболочка помещает его в фоновый режим, затем оболочка запускает bzgrep. (Но есть небольшая оговорка, с объяснением, включающим перенаправление файлов и буферизацию потока файлов, потенциально вызывающую разбиение / искажение очень небольшой части строк в выходном файле: увидите ли вы это, будет зависеть от того, как grep, bzgrep, и libc stdio.h функции реализованы. В большинстве реализаций я считаю, что передача команды по конвейеру перед перенаправлением в файл позволит избежать проблемы, поэтому вы можете сделать { foo & bar; } | cat - >file как обходной путь.)

Вы можете связать команды вместе с помощью &&, что позволит вам запускать каждую команду.

вы также можете добавить >> textfile.txt в конец каждой команды, чтобы вывод попадал в файл, а затем отправлял этот файл по почте.