Різнокольоровий греп


30

Я намагаюся отримати кожну команду grep, щоб виділити її результати іншим кольором. Я можу це зробити вручну з такою лінією:

ls -l GREP_COLORS='mt=01;32' grep c | GREP_COLORS='mt=01;31' grep o | GREP_COLORS='mt=01;34' grep n | GREP_COLORS='mt=01;36' grep f

Кожен cсимвол буде виділений зеленим кольором, а кожен oсимвол буде виділено червоним кольором тощо.

Щоб цей приклад працював, вам потрібно забезпечити, щоб ви завжди мали --color=alwaysсвої команди grep. Я встановив це в моєму, .bashrc так що греп завжди матиме кольори:

export GREP_OPTIONS='--color=always'


Що я намагаюся досягти, це обернути цю функціональність псевдонімом, щоб я міг просто зателефонувати grepта мати різну GREP_COLORSцінність кожного разу. Я розумію розгляд декількох оболонок для кожної нової грейпи, і я намагаюся досягти цього, створюючи деякі файли (по одному для кожного кольору), щоб вказати, що вони вже використовувались.

Я робив кілька спроб, але як не дивно, цей, здається, працює "найкраще". У мене це є .bashrc:

alias mg="mygrep"
mygrep(){
    # define possible colors
    COLORS=("01;32" "01;31" "01;34" "01;36")
    COUNTER=0
    NUM=0
    # as long as the color has already been used, keep searching
    while [ -f /home/lior/Desktop/mygrep_$NUM ]; do
        # get a random index
        let NUM=`shuf --input-range=0-$(( ${#COLORS[*]} - 1 )) | head -1`
        wait ${!}
        $(( COUNTER+=1 ))
        if [ "$COUNTER" -ge ${#COLORS[@]} ]; then
            # remove all color locks
            rm /home/lior/Desktop/mygrep_*
            wait ${!}
        fi
    done
    # mark this color as used
    touch /home/lior/Desktop/mygrep_$NUM
    wait ${!}

    # lets go!
    GREP_COLORS="mt=${COLORS[$NUM]}" grep "$@"
}

Я використовую цей псевдонім так:

ll | mg c | mg o | mg n | mg f

Результати досить класні. Однак є деякі помилки, які щоразу дещо відрізняються. Ось кілька скріншотів:

Схоже, як оболонка проходить через кожну команду труби, попередня функція ще не закінчила її виконання. Він намагається видалити файли, які вже не існують. Я не надто впевнений, звідки command not foundберуться інші помилки.

Як бачите, я вклав декілька waitкоманд, щоб спробувати дозволити маніпуляцію файлом завершено, але це, здається, не надто добре. Ще я спробував використовувати спільну пам’ять, /dev/shmале це дало подібні результати.

Як би я пішов про отримання бажаних результатів?

Примітка:

Я шукаю відповіді, які просто перетягують команду grep, оскільки вона має багато функціональних можливостей, які я хочу використати, і я маю намір вставити іншу логіку між трубами, тому не хочу вводити відразу всі пошукові терміни. Я також не шукаю інших "греп-подібних" інструментів. Вибачте від @terdon, який уже опублікував приголомшливу пропозицію за перл .


Ваш перший приклад не відповідає тому, що ви пояснюєте в частині, що залишилася, просто сказавши.
Бернхард

@bernhard Я не розумію, що ви маєте на увазі. Моя мета - використовувати мій псевдонім як частину більшої команди, використовуючи трубопроводи ... Будь ласка, дайте мені знати, про яке протиріччя ви говорите ...
Lix

Я думав, ти хочеш використовувати свій псевдонім і поза трубами. Так чи інакше, ваш перший приклад не працює для мене. Ви пробували alias mg="mygrep; grep"?
Бернхард

@Bernhard - Я працюю над коробкою ubuntu 12.04. Я не був би здивований, якби були незначні розбіжності ... Я спробував вашу пропозицію, проблема в тому, що mygrep;перетворюється на нову команду сама по собі і потік даних втрачається. Вхідна труба з боку lsбуде проходити в mygrep;та не грепати. Принаймні так я це розумію.
Лікс

@ Бернхард - Ага .. Я думаю, я знаю, чому це не працювало для тебе. Вам потрібно переконатися, що у вас є --color=alwaysвсі ваші команди grep. Я це встановив у всьому світі .bashrc. Я це відредагував у публікації.
Лікс

Відповіді:


6

Ось інший підхід. У мене є невеликий сценарій Perl, який я вже розмістив в іншій відповіді, який підкреслить надані користувачем візерунки різними кольорами. Трохи модифікована версія сценарію буде діяти так grep:

#!/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 : makes the search case sensitive
-c : comma separated list of colors;

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_blue', 
       'bright_white on_yellow', '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]='\*';
}

# Setting $| to non-zero forces a flush right away and after 
# every write or print on the currently selected output channel. 
$|=1;

while (my $line=<>) 
{ 
    my $want=0;
    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;
           $want++;
        }
    }
    else{
        if($line=~/$patterns[$c]/i){
          $line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ige;
          $want++;
        }
      }
    }
print STDOUT $line if $want>0;
}

Якщо ви збережете цей скрипт як cgrepдесь у своєму PATHі зробите його виконуваним, ви можете вказати до 10 різних шаблонів, кожен з яких буде надрукований іншим кольором:

введіть тут опис зображення

$ cgrep -h
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 : makes the search case sensitive
-c : comma separated list of colors;

5

Кожен виклик grepу трубі працює в окремій оболонці, тому вам потрібно буде пройти деякий стан між ними. Наступне рішення - це непростий спосіб впоратися з файлом, який зберігає кольоровий індекс та файл блокування, який гарантує, що одночасні дзвінки не читають однакове значення:

#!/usr/bin/env bash
color_index_file=~/.gitcolor
color_index_lock_file=/tmp/$(basename $0)

colors=()
for index in {31..34}
do
    colors+=("01;$index")
done

until mkdir "$color_index_lock_file" 2>/dev/null
do
    :
done

color_index=$(($(cat "$color_index_file" || echo 0) + 1))

if [[ $color_index -ge ${#colors[@]} ]]
then
    color_index=0
fi

printf "$color_index" > "$color_index_file"
rmdir "$color_index_lock_file"

GREP_COLORS="mt=01;${colors[$color_index]}" grep --color=always "$@"

Перевірте, якщо ви назвали свою копію cgrepта помістили її на свою PATH:

echo foobarbaz | cgrep foo | cgrep bar | cgrep baz

Єдині змінні, які дійсно потребують підтримання, - це COLOR_INDEXі GREP_COLORS. Я намагався експортувати їх у кінці функції без успіху. Це ви мали на увазі? Просто мати export VAR, правда?
Лікс

О - і так .. нерозумний друк там COLOR_TOGGLE. Дякуємо за те, що це
спіймали

1
@ l0b0 Експортер також не працює для мене, доведеться подати зворотну заяву, поки він дійсно не відповість на питання.
Бернхард

@Bernhard Це працює для вас?
l0b0

Дякуємо за ваш внесок! Я включив вашу grep "$@"пропозицію - це впорядковувало псевдонім, щоб запустити функцію, а потім виконати grep.
Лікс

1

Якщо ви добре вживаєте регулярних виразів, ви можете перевірити grc та grcat. grc називає grcat.

grcat використовує конфігураційні файли, куди ви можете додавати регулярні вирази для відповідності тексту, який відображатиметься у кожному кольорі. Він також має ряд інших варіантів. Він за замовчуванням застосовує кольорові файли журналу системи.

Залежно від того, що ви маєте на увазі для свого остаточного сценарію, ви зможете розфарбувати результат лише однією командою.

Трюк полягає в правильному визначенні регулярних виразів для кожного "поля" у вашому джерелі даних. Це буде набагато простіше, якщо ваші дані відносно однакові за структурою.

Востаннє, коли я спробував це, я не зайшов занадто далеко, але, можливо, я ще раз піду на це, тому що я трохи краще в регексах, ніж я був тоді.

Існує також команда tput, за допомогою якої можна надсилати інформацію (наприклад, зміни кольору) безпосередньо на ваш термінальний пристрій.

Обидва підходи висвітлюються в публікації нижче. Він говорить про команду find, але її можна застосувати до виводу будь-якої команди.

Кольоровий вихід?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.