Цветовые регулярные выражения - без промахов

Когда используешь grep --color=always Я могу получить красивую цветовую подсветку для регулярных выражений.

Тем не мение, grep возвращает только строки с хотя бы одним совпадением. Вместо этого я ищу способ просто выделить совпадения регулярных выражений, оставляя все остальные входные данные в покое, не отбрасывая строки без совпадений.

Я пытался заставить цвет работать с sedи прочитайте grep документация, но я не могу получить то, что хочу.

Если мое описание не очевидно, я хочу:

ВХОД:

  • Фред
  • Тед
  • красный
  • вести

Regex:

  • "* Красный"

ВЫХОД:

  • Фред (красным)
  • Тед
  • красный (в красном)
  • вести

Чтобы я мог сделать:

list_stuff | color_grep "make_this_stand_out_but_dont_hide_the_rest"

РЕДАКТИРОВАТЬ:

Я нашел решение, которое не очень красиво, но оно работает:

Спасибо: http://www.pixelbeat.org/docs/terminal_colours/

В частности, сценарий (который я изменил / упростил): http://www.pixelbeat.org/talks/iitui/sedgrep

function sedgrep ()
{
    C_PATT=`echo -e '\033[33;01m'`
    C_NORM=`echo -e '\033[m'`

    sed -s "s/$1/${C_PATT}&${C_NORM}/gi"
}

Все еще ищу более легкий способ сделать это!

7 ответов

Самое простое решение было бы использовать egrep --color=always 'text|^' который будет соответствовать всем началам строки, но только раскрасить желаемый текст.

Вот скрипт, который я использую для раскрашивания вывода.

Я думаю, что нашел идею / фрагмент в каком-то блоге или учебнике по bash / sed - не могу найти его больше, это было очень давно.

#!/bin/bash

red=$(tput bold;tput setaf 1)            
green=$(tput setaf 2)                    
yellow=$(tput bold;tput setaf 3)         
fawn=$(tput setaf 3)
blue=$(tput bold;tput setaf 4)           
purple=$(tput setaf 5)
pink=$(tput bold;tput setaf 5)           
cyan=$(tput bold;tput setaf 6)           
gray=$(tput setaf 7)                     
white=$(tput bold;tput setaf 7)          
normal=$(tput sgr0)                      

sep=`echo -e '\001'` # use \001 as a separator instead of '/'

while [ -n "$1" ] ; do
  color=${!1}
  pattern="$2"
  shift 2

  rules="$rules;s$sep\($pattern\)$sep$color\1$normal${sep}g"
done

#stdbuf -o0 -i0 sed -u -e "$rules"
sed -u -e "$rules"

Использование:

./colorize.sh color1 pattern1 color2 pattern2 ...

например

dmesg | colorize.sh red '.*Hardware Error.*' red 'CPU[0-9]*: Core temperature above threshold' \
green 'wlan.: authenticated.*' yellow 'wlan.: deauthenticated.*'

Не очень хорошо работает с перекрывающимися шаблонами, но я все равно нашел это очень полезным.

НТН

Эта маленькая функция хорошо работает в моей ZShell:

function color_grep {
    sed s/$1/$fg[yellow]$1$terminfo[sgr0]/g
}

(потребности

autoload colors zsh/terminfo

)

Может быть, вы можете сделать что-то подобное?

Изменить: Извините, это не будет работать с регулярными выражениями. Вам придется немного подправить...

То, как вы делаете это сейчас, вероятно, настолько же чисто, насколько вы можете этого ожидать, если, конечно, вы не напишите свой собственный инструмент grep. Если вам не обязательно заботиться о сохранении порядка вывода, вот другой способ, которым я могу придумать, чтобы сделать это:

function colormatch ()
{
    tee - | grep --color=always $1 | sort | uniq
}

Не так эффективно, как использование sed (больше процессов создано и тиражирование выходных данных), поэтому я, вероятно, рекомендую придерживаться вашего решения sed.

Вы могли бы использовать -C<num> опция grep, которая показывает вам <num> линии контекста вокруг вашего матча. Просто убедитесь, что <num> меньше, чем количество строк в вашем файле.

Я копаю эту маленькую утилиту Python. Если не в Debian, используйте alien для конвертации в rpm.

http://korpus.juls.savba.sk/~garabik/software/grc.html

regexp=.*red
colours="\033[38;5;160m"
count=once

Это хорошая страница о терминальных цветах.

http://www.pixelbeat.org/docs/terminal_colours/

(Английский королевы такой красочный.)

Я недавно сделал нечто похожее на фильтр. Я использую его, чтобы закрасить "заголовки" в хвосте несколькими файлами, например так:

tail -f access.log error.log foo.log | logcol.sh

Заголовки выглядят так:

==> access.log <==

Я запутался в быстрых изменениях между различными лог-файлами, поэтому этот logcol.sh помогает. ==> жестко задан для конкретного использования, но также может быть параметром.

#!/bin/sh
while read line
do
  if test `expr "$line" : "==>.*"`  -eq 0 ;
  then
    printf '\033[0m%s\n' "$line"
  else
    printf '\033[0;31m%s\n' "$line"
  fi
done

Может быть, не самый элегантный, но я думаю, что это вполне читабельно. Я надеюсь, что у меня нет опечаток;-) HTH, грабить

Другие вопросы по тегам