Grep colorato: visualizzazione dell'intero file con le corrispondenze evidenziate


509

Trovo che grepla --color=alwaysbandiera sia tremendamente utile. Tuttavia, grep stampa solo linee con corrispondenze (a meno che non si richiedano linee di contesto). Dato che ogni riga stampata ha una corrispondenza, l'evidenziazione non aggiunge la massima capacità possibile.

Mi piacerebbe davvero catun file e vedere l'intero file con le corrispondenze dei pattern evidenziate.

C'è un modo in cui posso dire a grep di stampare ogni riga letta indipendentemente dal fatto che ci sia una corrispondenza? So di poter scrivere uno script per eseguire grep su ogni riga di un file, ma ero curioso di sapere se questo era possibile con lo standard grep.


1
se si desidera più di un colore per più di un motivo (ad esempio messaggi di errore, avviso, informazioni, ecc.), utilizzaresed . la sedsoluzione ti offre più colori a costo di maggiore complessità (invece di circa 30 caratteri hai circa 60 caratteri).
Trevor Boyd Smith,

Con sed puoi anche evidenziare + return exit code , vedi esempio: askubuntu.com/a/1200851/670392
Noam Manos

Risposte:


797

Ecco alcuni modi per farlo:

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

152
Questo | $ trucco è pulito! Ben fatto, dovrò ricordarlo. Per quelli di voi che non sono esperti di espressioni regolari, "pattern | $" abbinerà le linee che hanno lo schema che state cercando E le linee che hanno una fine - cioè, tutte. Poiché la fine di una riga non è in realtà alcun carattere, la porzione colorata dell'output sarà solo il tuo modello. Grazie Ryan!
Zslayton,

55
È anche possibile omettere il "$": egrep --color "pattern|" file(di credito stackoverflow.com/a/7398092/50979 )
13ren

15
@Zack, il "|" operatore è un operatore OR, non un AND,
JBoy

16
@JBoy, stavo usando 'AND' nel modo inglese convenzionale piuttosto che nel modo logico booleano. Hai ragione, è davvero un 'o' operatore - corrisponde a questo e quello. : P Buon chiarimento.
Zslayton,

12
Sembra che "$" sia necessario se si abbina più di un modello. egrep --color "pattern1|pattern2|$". In caso contrario, l'evidenziazione del colore non avviene.
ZaSter,

91

Ecco qualcosa sulla stessa linea. È probabile che utilizzerai meno comunque, quindi prova questo:

less -p pattern file

Evidenzierà il modello e salterà alla prima occorrenza di esso nel file.


4
Funziona anche con piping (lettura da stding) usando -:… | less -p pattern -
phk,

3
@phk: puoi persino omettere il trattino.
In pausa fino a nuovo avviso.

Inoltre, l'aggiunta -idell'opzione renderà il case match insensibile come in less -ip pattern file.
Steve

... e se si less-R… | less -Rip introduction -
esegue il

48

Vorrei raccomandare ack - meglio di grep, uno strumento di ricerca di potenza per programmatori .

$ ack --color --passthru --pager = File di pattern "$ {PAGER: -less -R}"
$ ack --color --passthru file di pattern | meno -R
$ export ACK_PAGER_COLOR = "$ {PAGER: -less -R}"
$ ack - passa i file di pattern

Lo adoro perché per impostazione predefinita è la ricerca ricorsiva di directory (e fa molto più intelligente di grep -r), supporta espressioni regolari Perl complete (piuttosto che POSIXish regex(3)) e ha una visualizzazione del contesto molto più piacevole durante la ricerca di molti file.


2
Tuttavia, di volta in volta, non trova quello che voglio quando sono sicuro che deve essere lì. ackè intelligente, ma a volte troppo intelligente, ed escludeva il tipo di file in cui si trovava l'hit.
Michael Piefel

4
@MPi ack -acercherà tutti i tipi di file, escludendo comunque .git/ .svn/ecc.
effimero

1
Tuttavia, è bello che acknon cerchi tra le mie immagini, quindi -afa troppo. Ho aggiunto --type-set=freemarker=.ftlal mio ~/.ackrc, per fare un esempio.
Michael Piefel,

3
Con alcune modifiche di configurazione, grep fa già tutto ciò che fa ack, è più veloce e non omette mai i risultati come fanno a volte le whitelist di ack. Forse salva le tue impostazioni grep preferite in .bashrc. Il mio dice: function grp () {GREP_OPTIONS = "- rI --color --exclude-dir = \. Git --exclude = tags" grep "$ @"
Jonathan Hartley

22

Puoi usare il mio highlightscript da https://github.com/kepkin/dev-shell-essentials

È meglio che grepperché puoi evidenziare ogni partita con il suo colore .

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

Schermata del progetto Github


3
La domanda ha chiesto espressamente una soluzione utilizzando grep, che è un'utilità standard su macchine che eseguono * nix.
Zslayton,

1
Questo script è buono, ma non buono come coloutmenzionato in un'altra risposta.
Jonathan Hartley,

@JonathanHartley E perché è così? Non vedo alcun motivo per questo. Inoltre, questo script utilizza un'implementazione molto più semplice di colout, il che è utile se si desidera controllare cosa fa.
Ciao Arrivederci

@HelloGoodbye Sì, abbastanza giusto. Dovrei resistere alla sentenza. colout è più completo e potente, ma hai ragione a dire che è di conseguenza più complesso da usare e decodificare.
Jonathan Hartley,

@JonathanHartley Ha senso che sia più potente!
Ciao Arrivederci

19

Puoi anche creare un alias. Aggiungi questa funzione nel tuo .bashrc (o .bash_profile su osx)

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

Ora puoi usare l'alias in questo modo: " ifconfig | grepe inet" o " grepe css index.html".

(PS: non dimenticare source ~/.bashrcdi ricaricare Bashrc nella sessione corrente)


puoi anche usare solo egrep se è disponibile sul tuo sistema.
Tom,

1
Il piping del risultato di questo per meno perde le informazioni sul colore. Come lo impediresti?
Connor Clark,

5
@Hoten use --color=alwaysinvece di--color
limp_chimp

3
E, per far lessinterpretare i codici colore, usare less -R.
Eliah Kagan,

L'uso non quotato di $ 2 non è sicuro vuoto. In un bash preferirei fare la funzione grepe () {local pattern = "$ 1" shift egrep --color "$ pattern | ^" "$ @"} Ci scusiamo per il pasticcio di formattazione.
Robert Klemme,

16

Usa il coloutprogramma: http://nojhan.github.io/colout/

È progettato per aggiungere evidenziazioni di colore a un flusso di testo. Dato un regex e un colore (ad esempio "rosso"), riproduce un flusso di testo con le corrispondenze evidenziate. per esempio:

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

È possibile concatenare più invocazioni per aggiungere più luci di colore diverse:

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

Oppure puoi ottenere la stessa cosa usando una regex con N gruppi (parti tra parentesi della regex), seguita da un elenco separato da virgole di N colori.

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

1
Come notato altrove, la domanda ha espressamente chiesto una soluzione usando grep, che è un'utilità standard su macchine che eseguono * nix.
Zslayton,

4
@Zack ok, scusa. In realtà, se espandi il problema oltre grep, ed è già espanso nelle risposte, coloutè la soluzione migliore per il problema che hai avuto, il migliore di cui sono a conoscenza. Secondo la filosofia UNIX, i programmi dovrebbero essere scritti per fare bene una cosa. Perché grepsta filtrando il flusso di testo. Perché coloutsta colorando o evidenziando il flusso di testo.
user2683246

Questa è la risposta migliore, perché può applicare più luci colorate differenti ed coloutè uno strumento molto utile. Imparalo una volta, usalo in molte situazioni, piuttosto che imparare uno strumento per evidenziare i file di registro, un altro per evidenziare l'output del test, ecc.
Jonathan Hartley,

9

Uso rcg da "Linux Server Hacks", O'Reilly. È perfetto per quello che vuoi e può evidenziare più espressioni ognuna con colori diversi.

#!/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

L' -zopzione per grep è anche molto bella!

cat file1 | grep -z "pattern"

cosa fa questa daina? -z dice a grep di usare ASCII NUL come delimitatore di linea ...
vy32

6

Ho aggiunto questo al mio .bash_aliases:

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

3

Per evidenziare i motivi durante la visualizzazione dell'intero file, h può farlo.

Inoltre utilizza colori diversi per motivi diversi.

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

È inoltre possibile reindirizzare l'output di hto less -Rper una migliore lettura.

Per grep e usare 1 colore per ogni motivo, cxpgrep potrebbe essere una buona scelta.


1

Ok, questo è un modo,

wc -l filename

ti darà il conteggio delle righe - dì NN, quindi puoi farlo

grep -C NN --color=always filename

3
"-C 2147483647" se non vuoi prima fare il wc. L'uso di un numero elevato qui non sembra rallentare le cose.
Barrycarter,

1

Ecco uno script di shell che utilizza la funzione gsub di Awk per sostituire il testo che stai cercando con la sequenza di escape corretta per visualizzarlo in rosso brillante:

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

Usalo così:

$ ./cgrep pattern [file]

Sfortunatamente, non ha tutte le funzionalità di grep.

Per ulteriori informazioni, puoi fare riferimento a un articolo " So You Like Color " nel Linux Journal


1

Un'altra risposta ha menzionato l'opzione -Cn di grep che include n righe di contesto. A volte lo faccio con n = 99 come un modo rapido e sporco di ottenere [almeno] uno schermo di contesto quando il modello egrep sembra troppo complicato o quando sono su una macchina su cui non ho installato rcg e / o ccze.

Di recente ho scoperto cczequale è un colorante più potente. La mia unica lamentela è che è orientato allo schermo (come less, che non uso mai per quel motivo) a meno che non specifichi l'opzione -A per l'output "ANSI non elaborato".

+1 per la rcgmenzione sopra. È ancora il mio preferito poiché è così semplice da personalizzare in un alias. Qualcosa del genere è di solito nel mio ~ / .bashrc:

alias tailc = 'tail -f / my / app / log / file | rcg invia "BOLD GREEN" riceve "CYAN" errore "RED" '


1

un altro modo sporco:

grep -A80 -B80 --color FIND_THIS IN_FILE

Ho fatto un

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

a bashrc.


1
questo è problematico se le cose che stai cercando non ci sono. Dì a causa di un errore, nel qual caso non otterrai nulla.
Paul Rubel,


0

Se vuoi evidenziare diversi motivi con colori diversi vedi questo script bash.

Utilizzo di base:

echo warn error debug info 10 nil | colog

È possibile modificare motivi e colori mentre si esegue premendo un tasto e quindi il tasto Invio.


0

Uso il seguente comando per scopi simili:

grep -C 100 searchtext file

Questo dirà grep per stampare 100 * 2 righe di contesto, prima e dopo il testo di ricerca evidenziato.


0

Ecco il mio approccio , ispirato alla soluzione di @ 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[@]}")
}

Questo accetta più argomenti (ma non consente di personalizzare i colori). Esempio:

$ noisy_command | highlight ERROR WARN

-1

Esiste un modo in cui posso dire a grep di stampare ogni riga letta indipendentemente dal fatto che ci sia una corrispondenza?

Opzione -C999farà il trucco in assenza di un'opzione per visualizzare tutte le linee di contesto. La maggior parte delle altre varianti di grep supportano anche questo. Tuttavia: 1) non viene prodotto alcun output quando non viene trovata alcuna corrispondenza e 2) questa opzione ha un impatto negativo sull'efficienza di grep: quando il -Cvalore è grande, potrebbe essere necessario memorizzare temporaneamente molte righe per consentire a grep di determinare quali linee di contesto per visualizzare quando si verifica una corrispondenza. Si noti che le implementazioni grep non caricano i file di input ma piuttosto leggono alcune righe o utilizzano una finestra scorrevole sull'input. La "parte prima" del contesto deve essere mantenuta in una finestra (memoria) per generare le linee di contesto "prima" in seguito quando viene trovata una corrispondenza.

Un modello come ^|PATTERNo PATTERN|$o qualsiasi sub-pattern di corrispondenza vuota per quella materia come [^ -~]?|PATTERNè un bel trucco. Tuttavia, 1) questi schemi non mostrano linee non corrispondenti evidenziate come contesto e 2) questo non può essere usato in combinazione con alcune altre opzioni grep, come -Fe -wper esempio.

Quindi nessuno di questi approcci mi soddisfa. Sto usando ugrep e grep migliorato con l'opzione -yper visualizzare in modo efficiente tutti gli output non corrispondenti come linee di contesto evidenziate dal colore. Altri strumenti simili a grep come ag e ripgrep offrono anche un'opzione pass-through. Ma ugrep è compatibile con GNU / BSD grep e offre un superset di opzioni grep come -ye -Q. Ad esempio, ecco quale opzione -ymostra quando combinata con -Q(UI di query interattiva per inserire modelli):

ugrep -Q -y FILE ...

Perché votare questo senza lasciare un commento? È più che giusto menzionare strumenti grep alternativi, come alcune delle altre risposte.
Dr. Alex RE,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.