Мне нужно найти в наших журналах почты определенный адрес электронной почты. Мы сохраняем текущий файл с именем почтовый журнал а также недельные файлы .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 в конец каждой команды, чтобы вывод попадал в файл, а затем отправлял этот файл по почте.