Colorp grep - przeglądanie całego pliku z podświetlonymi dopasowaniami


509

Uważam grep, że --color=alwaysflaga jest niezwykle przydatna. Jednak grep drukuje tylko linie z dopasowaniami (chyba że poprosisz o linie kontekstu). Biorąc pod uwagę, że każda drukowana linia ma takie samo dopasowanie, wyróżnianie nie dodaje tyle możliwości, ile mogłoby.

Naprawdę chciałbym catzobaczyć plik i zobaczyć cały plik z zaznaczonymi dopasowaniami wzorca.

Czy jest jakiś sposób, aby powiedzieć grepowi, aby drukował każdą czytaną linię, niezależnie od tego, czy istnieje dopasowanie? Wiem, że mógłbym napisać skrypt uruchamiający grep w każdej linii pliku, ale byłem ciekawy, czy jest to możliwe ze standardem grep.


1
jeśli chcesz więcej niż jednego koloru dla więcej niż jednego wzoru (tj. komunikatów o błędach, ostrzeżeniach, informacjach itp.), użyjsed . sedrozwiązanie dostaje wiele kolorów kosztem dodatkowej złożoności (zamiast około 30 znaków, które mają około 60 znaków).
Trevor Boyd Smith

Za pomocą sed możesz nawet wyróżnić + zwrócić kod wyjścia , patrz przykład: askubuntu.com/a/1200851/670392
Noam Manos

Odpowiedzi:


797

Oto kilka sposobów, aby to zrobić:

grep --color -E 'pattern|$' file
grep --color 'pattern\|$' file
egrep --color 'pattern|$' file

152
Ta sztuczka | $ jest fajna! Dobra robota, muszę to pamiętać. Dla tych z was, którzy nie są zaznajomieni z wyrażeniami regularnymi, „wzór | $” dopasuje linie, które mają wzorzec, którego szukasz, ORAZ linie, które mają koniec - to znaczy wszystkie. Ponieważ koniec linii nie jest tak naprawdę żadnymi znakami, pokolorowana część wyniku będzie tylko twoim wzorem. Dzięki Ryan!
zslayton

55
Możesz też pominąć „$”: egrep --color "pattern|" file(kredyt stackoverflow.com/a/7398092/50979 )
13ren

15
@Zack, „|” operator jest operatorem OR, a nie AND,
JBoy

16
@Joy, używałem „ORAZ” w konwencjonalny angielski sposób, a nie logiczną logikę. Masz rację, to rzeczywiście operator „lub” - pasuje do tego i tamtego. : P Dobre wyjaśnienie.
zslayton,

12
Wygląda na to, że „$” jest potrzebne, jeśli pasuje więcej niż jeden wzór. egrep --color "pattern1|pattern2|$". W przeciwnym razie podświetlenie kolorów nie nastąpi.
ZaSter

91

Oto coś w tym samym stylu. Możliwe, że i tak będziesz używać mniej, więc spróbuj tego:

less -p pattern file

Podświetli wzór i przejdzie do pierwszego wystąpienia w pliku.


4
Działa również z orurowaniem (czytanie ze stdinga) przy użyciu -:… | less -p pattern -
phk

3
@phk: Możesz nawet pominąć myślnik.
Wstrzymano do odwołania.

Ponadto dodanie tej -iopcji sprawi, że wielkość liter w dopasowaniu będzie niewrażliwa less -ip pattern file.
steveb

... a jeśli rurociągów w ANSI-kolorowego wkładu, zapewniają lessz -Rprzełącznikiem:… | less -Rip introduction -
Abdull

48

Chciałbym polecić ack - lepsze niż grep, narzędzie wyszukiwania mocy dla programistów .

$ ack --color --passthru --pager = Pliki wzorców „$ {PAGER: -less -R}”
$ ack --color --passthru pliki sygnatur | mniej -R
$ export ACK_PAGER_COLOR = "$ {PAGER: -less -R}"
$ ack - pliki sygnatur passthru

Uwielbiam to, ponieważ domyślnie korzysta z rekurencyjnego przeszukiwania katalogów (i jest o wiele mądrzejsze niż grep -r), obsługuje pełne wyrażenia regularne Perla (zamiast POSIXish regex(3)) i ma znacznie ładniejszy kontekst wyświetlania podczas przeszukiwania wielu plików.


2
Jednak od czasu do czasu nie znajduje tego, czego chcę, kiedy jestem pewien, że musi tam być. ackjest sprytny, ale czasem zbyt sprytny i wyklucza typ pliku, w którym było trafienie.
Michael Piefel

4
@MPi ack -aprzeszuka wszystkie typy plików, wciąż wykluczając .git/ .svn/itp.
efhemient

1
Fajnie jest jednak, że acknie przeszukuje moich zdjęć, więc -arobi to za dużo. Dodałem --type-set=freemarker=.ftldo siebie ~/.ackrc, aby podać jeden przykład.
Michael Piefel

3
Po kilku poprawkach w konfiguracji grep już robi wszystko, co robi, jest szybszy i nigdy nie pomija wyników, jak czasami robią to białe listy ack. Być może zapisz swoje preferowane ustawienia grep w .bashrc. Kopalnia brzmi: function () {GRP GREP_OPTIONS = "- rI --color --exclude-dir = \ git --exclude = tagi." Grep "$ @"
Jonathan Hartley

22

Możesz użyć mojego highlightskryptu z https://github.com/kepkin/dev-shell-essentials

Jest to lepsze niż grepdlatego, że możesz podświetlić każde dopasowanie własnym kolorem .

$ command_here | highlight green "input" | highlight red "output"

Zrzut ekranu z projektu Github


3
Pytanie wyraźnie dotyczy rozwiązania używającego grep, które jest standardowym narzędziem na komputerach z * nix.
zslayton

1
Ten skrypt jest dobry, ale nie tak dobry, jak coloutwspomniano w innej odpowiedzi.
Jonathan Hartley,

@JonathanHartley I dlaczego tak jest? Nie widzę żadnego powodu. Poza tym ten skrypt używa znacznie prostszej implementacji niż colout, co jest dobre, jeśli chcesz sprawdzić, co robi.
HelloGoodbye,

@HelloGoodbye Tak, w porządku. Powinienem wstrzymać się od wyroku. colout jest bardziej dokładny i potężny, ale masz rację, że jest odpowiednio bardziej skomplikowany w użyciu i inżynierii wstecznej.
Jonathan Hartley

@JonathanHartley To ma sens, że ma większą moc!
HelloGoodbye 15.01.2019

19

Możesz także utworzyć alias. Dodaj tę funkcję do swojego .bashrc (lub .bash_profile w systemie OSX)

function grepe {
    grep --color -E "$1|$" $2
}

Możesz teraz używać takiego aliasu: „ ifconfig | grepe inet” lub „ grepe css index.html”.

(PS: nie zapomnij source ~/.bashrcprzeładować bashrc w bieżącej sesji)


możesz także użyć po prostu egrep, jeśli jest dostępny w twoim systemie.
Tom

1
Przekazanie wyniku tego w celu zmniejszenia traci informacje o kolorze. Jak mógłbyś temu zapobiec?
Connor Clark,

5
@ Korzystanie z Hoten --color=alwayszamiast--color
limp_chimp

3
Aby lessinterpretować kody kolorów, użyj less -R.
Eliah Kagan

Nieocenione użycie 2 $ nie jest całkowicie bezpieczne. W skrócie wolałbym wykonać funkcję grepe () {local pattern = "$ 1" shift egrep --color "$ pattern | ^" "$ @"}} Przepraszamy za bałagan z formatowaniem.
Robert Klemme,

16

Użyj coloutprogramu: http://nojhan.github.io/colout/

Służy do dodawania wyróżnień kolorów do strumienia tekstowego. Biorąc pod uwagę wyrażenie regularne i kolor (np. „Czerwony”), odtwarza strumień tekstowy z podświetlonymi dopasowaniami. na przykład:

# cat logfile but highlight instances of 'ERROR' in red
colout ERROR red <logfile

Możesz połączyć wiele wywołań, aby dodać wiele różnych wyróżnień kolorów:

tail -f /var/log/nginx/access.log | \
    colout ' 5\d\d ' red | \
    colout ' 4\d\d ' yellow | \
    colout ' 3\d\d ' cyan | \
    colout ' 2\d\d ' green

Lub możesz osiągnąć to samo, używając wyrażenia regularnego z N grupami (części wyrażenia w nawiasach), a następnie oddzielonej przecinkami listy N kolorów.

vagrant status | \
    colout \
        '\''(^.+  running)|(^.+suspended)|(^.+not running)'\'' \
        green,yellow,red

1
Jak zauważono w innym miejscu, pytanie wyraźnie dotyczyło rozwiązania wykorzystującego grep, które jest standardowym narzędziem na komputerach z * nix.
zslayton

4
@Zack ok, przepraszam. W rzeczywistości, jeśli rozwiążesz problem poza nim grep, a jest on już rozwinięty w odpowiedziach, coloutjest to najlepsze rozwiązanie problemu, jaki miałeś, najlepsze, o czym jestem świadomy. Zgodnie z filozofią UNIX, programy powinny być napisane, aby zrobić jedną rzecz dobrze. Bo grepfiltruje strumień tekstu. Bo coloutto jest kolorowanie lub wyróżnianie strumienia tekstu.
user2683246

To najlepsza odpowiedź, ponieważ może stosować wiele różnych kolorowych podświetleń i coloutjest tak bardzo użytecznym narzędziem. Naucz się tego raz, używaj go w wielu sytuacjach, zamiast uczyć się jednego narzędzia do podświetlania plików dziennika, drugiego do podświetlania wyników testowych itp.
Jonathan Hartley

9

Używam rcg z „Linux Server Hacks”, O'Reilly. Jest idealny do tego, czego chcesz i może wyróżniać wiele wyrażeń w różnych kolorach.

#!/usr/bin/perl -w
#
#       regexp coloured glasses - from Linux Server Hacks from O'Reilly
#
#       eg .rcg "fatal" "BOLD . YELLOW . ON_WHITE"  /var/adm/messages
#
use strict;
use Term::ANSIColor qw(:constants);

my %target = ( );

while (my $arg = shift) {
        my $clr = shift;

        if (($arg =~ /^-/) | !$clr) {
                print "Usage: rcg [regex] [color] [regex] [color] ...\n";
                exit(2);
        }

        #
        # Ugly, lazy, pathetic hack here. [Unquote]
        #
        $target{$arg} = eval($clr);

}

my $rst = RESET;

while(<>) {
        foreach my $x (keys(%target)) {
                s/($x)/$target{$x}$1$rst/g;
        }
        print
}

7

-zRozwiązaniem dla grep jest również bardzo śliskie!

cat file1 | grep -z "pattern"

co robi ta łania? -z mówi grepowi, aby używał ASCII NUL jako separatora linii ...
vy32 31.10.19

6

Dodałem to do moich .bash_aliases:

highlight() {
  grep --color -E "$1|\$"
}

3

Aby podświetlić wzorce podczas przeglądania całego pliku, h może to zrobić.

Dodatkowo używa różnych kolorów dla różnych wzorów.

cat FILE | h 'PAT1' 'PAT2' ...

Możesz także przesyłać dane wyjściowe do hdo w less -Rcelu lepszego odczytu.

Aby grep i użyć 1 koloru dla każdego wzoru, cxpgrep może być dobrym dopasowaniem.


1

Ok, to jest jeden sposób,

wc -l filename

poda ci liczbę linii - powiedz NN, to możesz zrobić

grep -C NN --color=always filename

3
„-C 2147483647”, jeśli nie chcesz najpierw wc. Używanie dużej liczby tutaj nie wydaje się spowalniać rzeczy.
barrycarter

1

Oto skrypt powłoki, który korzysta z funkcji gsub Awk, aby zastąpić szukany tekst odpowiednią sekwencją zmiany znaczenia, aby wyświetlać go na czerwono:

#! /bin/bash
awk -vstr=$1 'BEGIN{repltext=sprintf("%c[1;31;40m&%c[0m", 0x1B,0x1B);}{gsub(str,repltext); print}' $2

Używaj go w ten sposób:

$ ./cgrep pattern [file]

Niestety nie ma wszystkich funkcji grep.

Więcej informacji można znaleźć w artykule „ So You Like Colour ” w Linux Journal


1

Jedna inna odpowiedź wspomniała o przełączniku grep -Cn, który zawiera n wierszy kontekstu. Czasami robię to z n = 99 jako szybki i brudny sposób na uzyskanie [przynajmniej] pełnego kontekstu, gdy wzorzec egrep wydaje się zbyt wierny lub gdy jestem na komputerze, na którym nie zainstalowałem rcg i / lub ccze.

Niedawno odkryłem, cczektóry jest bardziej wydajnym koloryzatorem. Moją jedyną skargą jest to, że jest zorientowany na ekran (jak less, którego nigdy nie używam z tego powodu), chyba że podasz przełącznik -A dla wyjścia „surowego ANSI”.

+1 za rcgwzmiankę powyżej. Nadal jest moim ulubionym, ponieważ można go łatwo dostosować w aliasie. Coś takiego jest zwykle w moim ~ / .bashrc:

alias tailc = 'tail -f / my / app / log / file | rcg wyślij „BOLD GREEN” otrzymaj „CYAN” błąd „RED”


1

inny brudny sposób:

grep -A80 -B80 --color FIND_THIS IN_FILE

Zrobiłem

alias grepa='grep -A80 -B80 --color'

w bashrc.


1
jest to problematyczne, jeśli nie ma tam rzeczy, których szukasz. Powiedz z powodu błędu, w którym to przypadku nic nie otrzymasz.
Paul Rubel,


0

Jeśli chcesz wyróżnić kilka wzorów w różnych kolorach, zobacz ten skrypt bash.

Podstawowe użycie:

echo warn error debug info 10 nil | colog

Możesz zmieniać wzory i kolory podczas uruchamiania, naciskając jeden klawisz, a następnie klawisz Enter.


0

Używam następującego polecenia w podobnym celu:

grep -C 100 searchtext file

Powie to grep, aby wydrukować 100 * 2 wierszy kontekstu przed i po podświetlonym wyszukiwanym tekście.


0

Oto moje podejście , zainspirowane rozwiązaniem @ kepkin:

# Adds ANSI colors to matched terms, similar to grep --color but without
# filtering unmatched lines. Example:
#   noisy_command | highlight ERROR INFO
#
# Each argument is passed into sed as a matching pattern and matches are
# colored. Multiple arguments will use separate colors.
#
# Inspired by https://stackoverflow.com/a/25357856
highlight() {
  # color cycles from 0-5, (shifted 31-36), i.e. r,g,y,b,m,c
  local color=0 patterns=()
  for term in "$@"; do
    patterns+=("$(printf 's|%s|\e[%sm\\0\e[0m|g' "${term//|/\\|}" "$(( color+31 ))")")
    color=$(( (color+1) % 6 ))
  done
  sed -f <(printf '%s\n' "${patterns[@]}")
}

To akceptuje wiele argumentów (ale nie pozwala ci dostosowywać kolorów). Przykład:

$ noisy_command | highlight ERROR WARN

-1

Czy jest jakiś sposób, aby powiedzieć grepowi, aby drukował każdą czytaną linię, niezależnie od tego, czy istnieje dopasowanie?

Opcja -C999załatwi sprawę w przypadku braku opcji wyświetlania wszystkich linii kontekstu. Większość innych wariantów grep również to obsługuje. Jednak: 1) nie jest generowany żaden wynik, gdy nie znaleziono dopasowania i 2) ta opcja ma negatywny wpływ na wydajność grep: gdy -Cwartość jest duża, to wiele linii może wymagać tymczasowego przechowywania w pamięci, aby grep mógł określić, które linie kontekstu do wyświetlenia, gdy nastąpi dopasowanie. Zauważ, że implementacje grep nie ładują plików wejściowych, a raczej odczytują kilka wierszy lub używają przesuwanego okna nad danymi wejściowymi. Kontekst „przed częścią” musi być przechowywany w oknie (pamięci), aby wyprowadzić linie kontekstu „przed” później, gdy zostanie znalezione dopasowanie.

Wzorzec taki jak ^|PATTERNlub PATTERN|$dowolny pod-wzorzec pasujący do pustych elementów, na przykład, [^ -~]?|PATTERNjest fajną sztuczką. Jednak 1) te wzory nie pokazują niepasujących linii podświetlonych jako kontekst i 2) nie można tego użyć w połączeniu z niektórymi innymi opcjami grep, takimi jak -Fi -wna przykład.

Żadne z tych podejść nie jest dla mnie satysfakcjonujące. Używam ugrep i ulepszonego grep z opcją -ywydajnego wyświetlania wszystkich niedopasowanych danych wyjściowych jako podświetlonych kolorem linii kontekstu. Inne narzędzia podobne do grep, takie jak ag i ripgrep, oferują również opcję przekazywania. Ale ugrep jest kompatybilny z GNU / BSD grep i oferuje super zestaw opcji grep, takich jak -yi -Q. Na przykład oto, co -ypokazuje opcja w połączeniu z -Q(interaktywny interfejs zapytania do wprowadzania wzorców):

ugrep -Q -y FILE ...

Po co głosować bez komentarza? Wspominanie o alternatywnych narzędziach grep, takich jak niektóre inne odpowiedzi, jest więcej niż uczciwe.
Dr Alex RE
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.