Вопрос или проблема
Мне интересно, есть ли в стандартном наборе инструментов Unix программа, такая как grep
, которая вместо того, чтобы фильтровать строки, содержащие строку, просто выводит тот же ввод, но выделяя или окрашивая выбранную строку.
Я думал сделать это сам (должно быть достаточно просто), но, возможно, это уже существует как команда Unix.
Я планирую использовать это для мониторинга логов, поэтому я бы сделал что-то вроде этого:
tail -f logfile.log | highlight "error"
Обычно, когда я отслеживаю логи, мне нужно найти конкретную строку, но я также хочу знать, что написано до и после этой строки, поэтому фильтрация иногда недостаточна.
Существует ли что-то подобное?
Это забавный трюк с базовой командой grep
. Он состоит из использования двух фильтров: того, который вы хотите применить, и фиктивного, который соответствует всем строкам, но не создает выделение. Этот фиктивный фильтр может быть как ^
(начало строки), так и $
(конец строки).
grep "^\|text" --color="always" file
или
grep -E "^|text" --color="always" file
Посмотрите пример:
$ cat a
hello this is
some text i wanted
to share with you
$ grep "^\|text" --color="always" a
hello this is
some text i wanted # "text" выделен
to share with you
Существует инструмент под названием ack
. Вы можете найти его на http://beyondgrep.com, и это действительно инструмент, превосходящий grep. Его самое распространенное использование заключается в выполнении такой задачи, как find . -name "*.java" --print | xargs grep clazz
или подобной. Потому что мы делаем это все время.
Просто ack clazz
, и вы получите вывод. Он выполняет поиск по соответствующим файлам (не пытается выполнять grep по двоичным файлам) и также позволяет получать вывод в цвете.
Если вы используете его с опцией --passthru
, он будет выводить весь входной поток, выделяя подходящие области цветом.
--passthru
Выводить все строки, независимо от того, соответствуют они или нет
Как говорится в документации, если для файла указать -
, он будет принимать STDIN:
Если указаны какие-либо файлы или каталоги, проверяются только эти файлы и каталоги. Кроме того, ack может выполнять поиск по STDIN, но только если не указаны файлы или каталоги или если один из них – “-“.
Таким образом, извините за злоупотребление cat
(и каламбур – см. ниже), вы можете это использовать:
$ cat file | ack --passthru pattern
$ cat file | ack --passthru pattern -
Это будет принимать вывод от пайпа и отправлять его через ack
, который будет выводить все строки (с --passthru
) с выделенным шаблоном.
Это именно тот инструмент, который вам нужен (и немного больше). Это стандартный пакет для многих менеджеров пакетов. См. http://beyondgrep.com/install/ для вашего любимого.
_ /| \'o.O' =(___)= U ack --thpppt!
(Если вы не узнали, это Билл Кот, хотя поиск изображений может также помочь – не кликайте на наборы Майли Сайрус)
Вы могли бы использовать флаг grep -C
, который дает n строк контекста, например, grep -C 3
будет выводить 3 строки до и после совпадения. Существуют также -B
и -A
для до и после.
Если вы ищете регулярное выделение конкретных строк, например, специфичных для форматов логов, возможно, стоит использовать python pygmentize с кастомным лексером, так как он основан на регулярных выражениях, вы будете удивлены, насколько это просто. Последнее также имеет преимущество быть кросс-платформенным, хотя некоторые терминалы плохо работают с цветом.
Я поклонник hhighlighter от Паоло Антинори. https://github.com/paoloantinori/hhighlighter
Плюс этой команды в том, что она может выделять до 10 слов уникальными цветами. Просто направьте вывод команды в h
с словами для выделения.
Например, tail -f /var/log/somelog.log | h "ERROR"
выдаст:
Некоторые примеры с его сайта:
Я написал небольшой скрипт, который будет окрашивать любую строку, которую вы ему передадите:
#!/usr/bin/env perl
use Getopt::Std;
use strict;
use Term::ANSIColor;
my %opts;
getopts('hic:l:',\%opts);
if ($opts{h}){
print<<EoF;
Use -l to specify the pattern(s) to highlight. To specify more than one
pattern use commas.
-l : A Perl regular expression to be colored. Multiple expressions can be
passed as comma separated values: -l foo,bar,baz
-i : делает поиск чувствительным к регистру
-c : список цветов, разделенный запятыми;
EoF
exit(0);
}
my $case_sensitive=$opts{i}||undef;
my @color=('bold red','bold blue', 'bold yellow', 'bold green',
'bold magenta', 'bold cyan', 'yellow on_magenta',
'bright_white on_red', 'bright_yellow on_red', 'white on_black');
if ($opts{c}) {
@color=split(/,/,$opts{c});
}
my @patterns;
if($opts{l}){
@patterns=split(/,/,$opts{l});
}
else{
$patterns[0]='\*';
}
# Установка $| в ненулевое значение обеспечивает немедленную очистку и после каждой записи или печати на текущий выбранный канал вывода.
$|=1;
while (my $line=<>)
{
for (my $c=0; $c<=$#patterns; $c++){
if($case_sensitive){
if($line=~/$patterns[$c]/){
$line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ge;
}
}
else{
if($line=~/$patterns[$c]/i){
$line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ige;
}
}
}
print STDOUT $line;
}
Если вы сохраните его как color
в каталоге, который находится в вашем $PATH
и сделаете исполняемым (chmod +x /usr/bin/color
), вы можете выделять соответствующий шаблон так:
echo -e "foo\nbar\nbaz\nbib" | color -l foo,bib
Это даст:
Как написано, скрипт имеет предопределенные цвета для 10 различных шаблонов, поэтому, предоставляя ему список, разделенный запятыми, как в примере выше, он будет окрашивать каждый из совпадающих шаблонов в разные цвета.
Я написал программу для этого некоторого времени назад. Я называю ее cgrep (цветной grep).
Вы можете скачать ее, скопировав секцию кода отсюда в пустой файл: http://wiki.tcl.tk/38096
Затем сделайте файл исполняемым и скопируйте его в один из ваших регулярных каталогов bin.
Она написана на tcl, поэтому вам нужно установить tcl (версии 8.5 и выше). Но большинство дистрибутивов Linux уже включают tcl, так как много программного обеспечения его использует (gitk, настройка ядра, expect и т.д.).
Синтаксис для окраски прост: регекс опция опция ..
. Вы можете использовать столько регексов, сколько вам нужно. Вот пример, который будет окрашивать ошибки в красный и предупреждения в желтый:
tail -f logfile | cgrep '^.*WARNING.*$' -fg yellow '^.*ERROR.*$' -fg red -bg yellow
Вы можете использовать эту команду
grep --color --context=1000
Или короче
grep --col -1000
Самый простой способ выглядит следующим образом, как мне кажется:
tail -f logfile.log | grep -e 'error' -e '**'
Нет необходимости ничего устанавливать.
Ну, я использую Fedora 21, и если я наберу
grep -E \|kk rs.c
он выведет все содержимое файла “rs.c”, выделяя любые вхождения “kk”.
Простой трюк — также сопоставить пустую строку или начало строки; любое из них даст нулевое совпадение для всех строк:
grep --color -e 'REGEXP' -e ''
grep --color -e 'REGEXP' -e ^
Или (с использованием расширенного синтаксиса регулярных выражений):
grep --color -E 'REGEXP|'
egrep --color 'REGEXP|'
Используйте less
. Строка поиска, найденная с помощью /
, является регулярным выражением, и вхождения будут выделены.
В моем .bashrc у меня есть эта функция. Я называю ее cgrep
, но здесь я даю ей немного более подходящее имя.
highlight() { grep -E --color "^|$1"; }
Я нахожу это полезным для чтения логов, например, где я хочу выделить ключевое слово, но видеть все, что происходит.
tail -f /var/log/SOMELOG | highlight KEYWORD
Вы можете просто направить ваш вывод на:
sed "s/\([Ee][Rr][Rr][Oo][Rr]\)/`tput rev`\1`tput rmso`/"
Здесь я использую регулярное выражение, которое будет совпадать с “error”, “ERROR”, “ErRoR” и т. д. во всех 32 возможных вариациях.
У меня в ~/.zshrc
определена следующая функция:
hl () {
sed s/$1/$'\e[1;31m'\&$'\e[0;m'/
}
Используйте ее с tail -f logfile.log | hl "error"
. Она добавляет escape-последовательность для Light Red перед выделенным словом и сброс на отсутствие цвета после слова. Вы можете найти другие цветовые коды здесь: http://tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html
.
Ответ или решение
Конечно, поиск и выделение ключевых слов в потоке данных — актуальная задача для многих ИТ-специалистов, особенно когда речь идет о мониторинге журналов (логов). Универсальный инструмент Unix "grep" позволяет выполнять поиск и фильтрацию строк, содержащих заданное регулярное выражение. Однако бывают случаи, когда необходимо не фильтровать, а лишь выделять требуемые строки в общем контексте данных.
Решение:
Чтобы выделять слова или фразы в потоке данных, вы можете воспользоваться рядом существующих решений, не создавая собственный инструмент с нуля. Вот несколько предложений:
-
Использование
grep
для выделения:
Командаgrep
может быть настроена на выделение найденных строк без их фильтрации. Использование флага--color
позволяет подсветить совпавшую область текста:grep --color=always -E '^|Ваш_текст'
Пример выше показывает весь текст с выделением искомого фрагмента без удаления остальных строк.
-
Утилита
ack
:
ack
— более функциональный инструмент, который также может использоваться для выделения текста. Команда выглядит следующим образом:tail -f logfile.log | ack --passthru "error"
Здесь
--passthru
обеспечивает отображение всех строк с выделением только совпадений, что идеально подходит для мониторинга в реальном времени. -
hhighlighter
от Паоло Антинори:
Еще один инструмент,hhighlighter
, позволяет выделять сразу несколько ключевых слов разными цветами, что удобно для комплексного анализа журналов:tail -f logfile.log | h "ERROR" "WARNING"
Подсвечиваются несколько ключевых слов разными цветами, облегчая выявление критических моментов в журнале.
-
Использование
sed
для подсветки:
Встроенный инструментsed
может использоваться для выделения текста с помощью управляющих последовательностей терминала:sed "s/Ваш_текст/`tput rev`&`tput sgr0`/g"
Такой подход позволяет выделить любое слово или фразу, используя обратную и обычную видеоинверсию.
-
Создание функции
highlight
в оболочке:
В файле конфигурации вашей оболочки можно создать пользовательскую функцию:highlight() { grep -E --color "^|$1"; }
Это позволяет удобно интегрировать выделение текста в ваши стандартные рабочие процессы.
Каждое из этих решений будет полезно для выделения и анализа текста в потоках данных, предоставляя более детальную картину происходящих событий, что важно для быстрого реагирования на выявленные ошибки или аномалии в логах. Подход выбирайте исходя из ваших требований и привычного окружения.