Вопрос или проблема
В bash, если я хочу выполнить команду и отобразить только те строки вывода, которые соответствуют определенному шаблону, я могу передать ее через grep
, например
файл testfile
hello
there
my
friends
команда
$ cat testfile | grep 'hello'
hello #это будет выделено
это выделит соответствие поиска и отобразит всю строку, на которой оно находится. Я могу использовать -A
и -B
, чтобы отобразить строки до и после этой строки. Мой вопрос: возможно ли выполнить команду и отобразить весь вывод как обычно, но выделить совпадения поиска, как это делает grep? Так мой вывод будет
hello #выделенное
there
my
friends
Чтобы использовать Color GREP для выделения только совпадающих шаблонов, но при этом не изменяя вывод:
grep --color=always -e "^" -e "hello" testfile
Первый шаблон будет соответствовать всем строкам (все строки будут напечатаны), второй шаблон (и любые следующие шаблоны) заставляет совпадающий текст выделяться цветом.
Поскольку первый шаблон соответствует всем строкам, но не совпадает с печатаемым символом, он не добавляет цветного выделения, поэтому не мешает читаемости выделенного текста.
Добавьте опцию -z
к вашей команде GNU grep:
cat testfile | grep --color=always -z 'hello'
или короче
grep --color=always -z 'hello' testfile
Это работает как с GNU grep, так и с grep на FreeBSD:
grep --color=always 'hello\|$'
Он соответствует тексту “hello” или (\|
) невидимой нулевой строке в конце каждой строки ($
). Вот почему каждая строка распечатывается, но только “hello” выделяется.
Возможно, у вас уже настроено --color=auto
в вашей оболочке. Тогда вам, вероятно, не нужно указывать --color=always
:
grep 'hello\|$'
Вы также можете упростить версию, используя egrep
(с расширенными регулярными выражениями), где |
для “или” выражения не нужно экранировать:
egrep 'hello|$'
Смотрите также аналогичный вопрос на StackOverflow: Colorized grep — просмотр всего файла с выделенными совпадениями
Аналогично предыдущему ответу, вы можете поймать все $
в конце строк:
cat testfile | grep --color -E "hello|$"
-E
(или --extended-regexp
) означает, что специальные символы должны быть экранированы с помощью \
. При его использовании |
будет восприниматься как условие регулярного выражения “ИЛИ”.
Grep |$
также поймает и распечатает все строки, которые имеют конец, но поскольку $ является скрытым символом, его нельзя выделить.
Обновление:
Если вы хотите распечатать весь вывод, но также возвращать код завершения, был найдено совпадение или нет, вы можете использовать команду perl:
cat testfile | \
perl -pe 'BEGIN {$status=1} END {exit $status} $status=0 if /hello/;'
Если вы предпочитаете sed – вот пример, как выделить все совпадения + вернуть код выхода, если совпадение не найдено: https://askubuntu.com/a/1200851/670392
Вот решение с использованием ripgrep
, современного, более удобного (на мой взгляд) и гораздо более быстрого заменителя grep
:
cat my-file | rg --passthru '<REGEX>'
Вы также можете легко настроить “цвет выделителя”:
# темно-красный текст на светло-желтом фоне:
cat my-file | rg --passthru --colors match:fg:124 --colors match:bg:229 '<REGEX>'
Смотрите man rg
(онлайн версия).
Для повседневного использования я создал алиас оболочки:
# в .bashrc
alias hl="rg --passthru --colors match:fg:124 --colors match:bg:229"
Теперь это так же просто, как cat my-file | hl '<REGEX>'
.
Дополняя верхний ответ выше. Функция highlight{} упомянутая в комментариях работает только когда данные передаются в нее. Следующий алиас, хоть и не идеален, но более полезен:
alias greph="grep --color=always -e^ -e"
Это работает с командами, такими как:
greph foo bar.txt
cat bar.txt | greph foo
Вместо -e '^'
, который не работает с -F
(--fixed-strings
), похоже, что -e ''
просто работает. Он соответствует каждой пустой строке, но, кажется, не активирует цветной вывод.
-z
хорошо подходит для вывода всего файла, как в ответе от bot779
, но чаще всего вам нужно контролировать, сколько строк нужно включить выше и ниже совпадения. Вы можете контролировать длину контекста с помощью -C <N>
, где N – это количество строк контекста. Смотрите пример ниже:
cat >testfile <<EOM
hello
there
my
friends
more
lines
to demonstrate
context
EOM
cat testfile | grep --color=always -C 2 friends
there
my
*friends* выделено
more
lines
Использование большого числа, такого как -C 1000
, также может ограничить вывод, если вывод, который вы фильтруете, слишком велик.
Есть гораздо более простой способ сделать это, чем использовать опцию --color
, как предлагают все другие ответы. Используйте команду tee. Пример:
cat my_file.txt | tee >(grep 'search_for_this')
Это отобразит полное содержимое my_file.txt
, и все экземпляры search_for_this
будут выделены.
Ответ или решение
Для выполнения задачи выделения совпадений в выводе команд в bash, сохраняя весь вывод неизменным, вы можете использовать несколько подходов, основанных на мощных инструментах, таких как grep
, perl
, sed
, и ripgrep
. Ниже представлены наиболее эффективные и универсальные методы, которые удовлетворяют вашим требованиям:
1. Использование grep
с параметрами
Вам необходимо применить следующий набор параметров для grep
, чтобы добиться желаемого эффекта:
grep --color=always 'запрашиваемый_шаблон\|$' ваш_файл.txt
В этом примере:
запрашиваемый_шаблон
– это тот текст, который вы хотите выделить.\|$
– означает, что мы также хотим отобразить конец каждой строки, что позволяетgrep
вывести все строки на экран.
Этот метод будет выводить все строки из файла, и каждое совпадение будет выделено.
2. Использование perl
Если вам необходимо не только выделять совпадения, но и отслеживать статус выхода команды (например, чтобы узнать, были ли совпадения), вы можете использовать команду perl
:
cat ваш_файл.txt | perl -pe 'BEGIN {$found=0} if (/запрашиваемый_шаблон/) {$found=1; $_=~s/(запрашиваемый_шаблон)/\e[31m$1\e[0m/g} END {exit !$found}'
Здесь:
BEGIN {$found=0}
иEND {exit !$found}
используют переменную для проверки, найдено ли совпадение, и устанавливают статус выхода.$_=~s/(запрашиваемый_шаблон)/\e[31m$1\e[0m/g
используется для дополнительного выделения текста с помощью ANSI-кодов.
3. Использование sed
Можете использовать sed
как альтернативу:
sed -e "s/\(запрашиваемый_шаблон\)/\x1b[31m\1\x1b[0m/g" ваш_файл.txt
Этот метод также позволяет выделить текст, используя ANSI-коды для цветовой разметки.
4. Применение ripgrep
Для более современных решений рассмотрите ripgrep
, который является мощной альтернативой grep
:
cat ваш_файл.txt | rg --passthru 'запрашиваемый_шаблон'
Этот инструмент не только поддерживает выделение совпадений, но и предоставляет возможность настроить цвет выделения.
5. Использование tee
Если вам нужно сохранить полный вывод в файл и одновременно отображать его на экране с выделением совпадений, используйте tee
:
cat ваш_файл.txt | tee >(grep --color=always 'запрашиваемый_шаблон')
Это покажет весь вывод на экране и выделит совпадения в отдельном потоке.
Заключение
Каждый из перечисленных методов позволяет вам эффективно работать с текстом в Linux, обеспечивая возможность выделения совпадений без потери важной информации. Выбор конкретного метода может зависеть от ваших предпочтений и требований к производительности. Рекомендуется протестировать несколько методов дляFinding наиболее удобного и подходящего для вашего сценария.