Grep colorisé - affichage de l'intégralité du fichier avec les correspondances en surbrillance

509

Je trouve que greple --color=alwaysdrapeau de 'est extrêmement utile. Cependant, grep imprime uniquement les lignes avec des correspondances (sauf si vous demandez des lignes de contexte). Étant donné que chaque ligne imprimée a une correspondance, la mise en évidence n'ajoute pas autant de fonctionnalités qu'elle le pourrait.

J'aimerais vraiment catun fichier et voir le fichier entier avec les correspondances de motifs en surbrillance.

Existe-t-il un moyen de dire à grep d'imprimer chaque ligne en cours de lecture, qu'il y ait ou non une correspondance? Je sais que je pourrais écrire un script pour exécuter grep sur chaque ligne d'un fichier, mais j'étais curieux de savoir si cela était possible avec la norme grep.

zslayton
la source
1
si vous voulez plus d'une couleur pour plus d'un motif (c.-à-d. messages d'erreur, d'avertissement, d'information, etc.), utilisezsed . la sedsolution vous offre plusieurs couleurs au prix d'une complexité supplémentaire (au lieu d'environ 30 caractères, vous avez environ 60 caractères).
Trevor Boyd Smith,
Avec sed, vous pouvez même mettre en surbrillance + retourner le code de sortie , voir exemple: askubuntu.com/a/1200851/670392
Noam Manos

Réponses:

797

Voici quelques façons de procéder:

grep --color -E 'pattern|$' file
grep --color 'pattern\|$' file
egrep --color 'pattern|$' file
Ryan Oberoi
la source
152
Cette astuce | $ est bien! Bien joué, je dois m'en souvenir. Pour ceux d'entre vous qui ne sont pas avertis des expressions régulières, "pattern | $" fera correspondre les lignes qui ont le modèle que vous recherchez ET les lignes qui ont une fin - c'est-à-dire toutes. Étant donné que la fin d'une ligne ne contient en fait aucun caractère, la partie colorisée de la sortie sera simplement votre motif. Merci Ryan!
zslayton
55
Vous pouvez également omettre le "$": egrep --color "pattern|" file(credit stackoverflow.com/a/7398092/50979 )
13ren
15
@Zack, le "|" opérateur est un opérateur OU, pas un ET,
JBoy
16
@JBoy, j'utilisais 'ET' de la manière anglaise conventionnelle plutôt que de la logique booléenne. Vous avez raison, il s'agit bien d'un opérateur «ou» - il correspond à ceci et cela. : P Bonne clarification.
zslayton
12
Il semble que le "$" soit nécessaire s'il correspond à plusieurs motifs. egrep --color "pattern1|pattern2|$". Sinon, la surbrillance des couleurs ne se produit pas.
ZaSter
91

Voici quelque chose dans le même sens. Il y a de fortes chances que vous utilisiez moins de toute façon, alors essayez ceci:

less -p pattern file

Il mettra en surbrillance le motif et passera à la première occurrence de celui-ci dans le fichier.

En pause jusqu'à nouvel ordre.
la source
4
Fonctionne également avec la tuyauterie (lecture de stding) en utilisant -:… | less -p pattern -
phk
3
@phk: Vous pouvez même omettre le tiret.
pause jusqu'à nouvel ordre.
De plus, l'ajout de l' -ioption rendra la casse de correspondance insensible comme dans less -ip pattern file.
steveb
... et si la tuyauterie est en entrée de couleur ANSI, prévoir lessl' -Rinterrupteur:… | less -Rip introduction -
Abdull
48

J'aimerais recommander ack - mieux que grep, un outil de recherche de puissance pour les programmeurs .

$ ack --color --passthru --pager = "$ {PAGER: -less -R}" fichiers de motif
$ ack --color --fassthru pattern files | moins -R
$ export ACK_PAGER_COLOR = "$ {PAGER: -less -R}"
$ ack - fichiers de motifs passthru

Je l'adore car il utilise par défaut la recherche récursive de répertoires (et est beaucoup plus intelligent que grep -r), prend en charge les expressions régulières Perl complètes (plutôt que POSIXish regex(3)) et a un affichage de contexte beaucoup plus agréable lors de la recherche de nombreux fichiers.

éphémère
la source
2
Cependant, de temps en temps, il ne trouve pas ce que je veux quand je suis certain qu'il doit être là. ackest intelligent, mais parfois trop intelligent, et il excluait le type de fichier dans lequel le hit était.
Michael Piefel
4
@MPi ack -arecherchera tous les types de fichiers, tout en excluant .git/ .svn/etc.
ephemient
1
Cependant, c'est cool qui ackne cherche pas dans mes images, en -afait trop. J'ai ajouté --type-set=freemarker=.ftlà mon ~/.ackrc, pour donner un exemple.
Michael Piefel
3
Avec quelques réglages de configuration, grep fait déjà tout ce que fait ack, est plus rapide et n'omet jamais les résultats comme le font parfois les listes blanches d'ack. Enregistrez peut-être vos paramètres grep préférés dans .bashrc. Le mien lit: function grp () {GREP_OPTIONS = "- rI --color --exclude-dir = \. Git --exclude = tags" grep "$ @"
Jonathan Hartley

22

Vous pouvez utiliser mon highlightscript sur https://github.com/kepkin/dev-shell-essentials

C'est mieux que grepparce que vous pouvez mettre en évidence chaque match avec sa propre couleur .

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

Capture d'écran du projet Github


3
La question demandait expressément une solution utilisant grep, qui est un utilitaire standard sur les machines exécutant * nix.
zslayton

1
Ce script est bon, mais pas aussi bon que coloutmentionné dans une autre réponse.
Jonathan Hartley

@JonathanHartley Et pourquoi en est-il ainsi? Je ne vois aucune raison à cela. De plus, ce script utilise une implémentation beaucoup plus simple que colout, ce qui est bien si vous voulez inspecter ce qu'il fait.
HelloGoodbye

@HelloGoodbye Ouais, assez bien. Je devrais retarder le jugement. colout est plus approfondi et plus puissant, mais vous avez raison de dire qu'il est en conséquence plus complexe à utiliser et à inverser.
Jonathan Hartley

@JonathanHartley Il est logique qu'il soit plus puissant!
HelloGoodbye

19

Vous pouvez également créer un alias. Ajoutez cette fonction dans votre .bashrc (ou .bash_profile sur osx)

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

Vous pouvez maintenant utiliser l'alias comme ceci: " ifconfig | grepe inet" ou " grepe css index.html".

(PS: n'oubliez pas source ~/.bashrcde recharger bashrc sur la session en cours)


vous pouvez également utiliser simplement egrep s'il est disponible sur votre système.
Tom

1
Le fait de canaliser le résultat vers moins perd les informations de couleur. Comment empêcheriez-vous cela?
Connor Clark

5
Utilisation @Hoten --color=alwaysau lieu de--color
limp_chimp

3
Et, pour faire lessinterpréter les codes couleurs, utilisez less -R.
Eliah Kagan du

L'utilisation non cotée de 2 $ n'est pas vierge en toute sécurité. Dans un bash, je préfère faire la fonction grepe () {local pattern = "$ 1" shift egrep --color "$ pattern | ^" "$ @"} Désolé pour le désordre de formatage.
Robert Klemme
16

Utilisez le coloutprogramme: http://nojhan.github.io/colout/

Il est conçu pour ajouter des reflets de couleur à un flux de texte. Étant donné une expression régulière et une couleur (par exemple "rouge"), il reproduit un flux de texte avec des correspondances mises en évidence. par exemple:

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

Vous pouvez chaîner plusieurs invocations pour ajouter plusieurs surbrillances de couleurs différentes:

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

Ou vous pouvez obtenir la même chose en utilisant une expression régulière avec N groupes (parties entre parenthèses de l'expression régulière), suivie d'une liste séparée par des virgules de N couleurs.

vagrant status | \
    colout \
        '\''(^.+  running)|(^.+suspended)|(^.+not running)'\'' \
        green,yellow,red
user2683246
la source
1
Comme indiqué ailleurs, la question demandait expressément une solution utilisant grep, qui est un utilitaire standard sur les machines exécutant * nix.
zslayton
4
@Zack ok, désolé. En fait, si vous développez le problème au grep- delà , et il est déjà développé dans les réponses, coloutc'est la meilleure solution au problème que vous avez eu, la meilleure que je sache. Selon la philosophie UNIX, les programmes doivent être écrits pour bien faire une chose. Car grepil filtre le flux de texte. Car coloutc'est coloriser ou surligner le flux de texte.
user2683246
C'est la meilleure réponse, car elle peut appliquer plusieurs reflets colorés différents, et coloutc'est un outil très utile. Apprenez-le une fois, utilisez-le dans de nombreuses situations, plutôt que d'apprendre un outil pour mettre en évidence les fichiers journaux, un autre pour mettre en surbrillance les résultats des tests, etc.
Jonathan Hartley
9

J'utilise rcg de "Linux Server Hacks", O'Reilly. Il est parfait pour ce que vous voulez et peut mettre en évidence plusieurs expressions chacune avec des couleurs différentes.

#!/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
}
dave1010
la source
7

L' -zoption pour grep est également assez lisse!

cat file1 | grep -z "pattern"
Abhishek Jaisingh
la source
qu'est-ce que cette biche? -z dit à grep d'utiliser ASCII NUL comme délimiteur de ligne ...
vy32
6

J'ai ajouté ceci à mes .bash_aliases:

highlight() {
  grep --color -E "$1|\$"
}
uronce
la source
3

Pour mettre en surbrillance des motifs lors de la visualisation de l'ensemble du fichier, h peut le faire.

De plus, il utilise différentes couleurs pour différents motifs.

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

Vous pouvez également diriger la sortie de hvers less -Rpour une meilleure lecture.

Pour grep et utiliser 1 couleur pour chaque motif, cxpgrep pourrait être un bon ajustement.

treulz
la source
1

Ok, c'est une façon,

wc -l filename

vous donnera le nombre de lignes - dites NN, alors vous pouvez faire

grep -C NN --color=always filename
nik
la source
3
"-C 2147483647" si vous ne voulez pas commencer par les WC. L'utilisation d'un grand nombre ici ne semble pas ralentir les choses.
barrycarter
1

Voici un script shell qui utilise la fonction gsub d'Awk pour remplacer le texte que vous recherchez par la séquence d'échappement appropriée pour l'afficher en rouge vif:

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

Utilisez-le comme ceci:

$ ./cgrep pattern [file]

Malheureusement, il n'a pas toutes les fonctionnalités de grep.

Pour plus d'informations, vous pouvez vous référer à un article " So You Like Color " dans Linux Journal

Wernsey
la source
1

Une autre réponse mentionne le commutateur -Cn de grep qui comprend n lignes de contexte. Je fais parfois cela avec n = 99 comme un moyen rapide et sale d'obtenir [au moins] un écran plein de contexte lorsque le modèle egrep semble trop compliqué, ou lorsque je suis sur une machine sur laquelle je n'ai pas installé rcg et / ou ccze.

J'ai récemment découvert cczequi est un colorant plus puissant. Mon seul reproche, c'est qu'il est orienté écran (comme less, que je n'utilise jamais pour cette raison), sauf si vous spécifiez le commutateur -A pour la sortie "raw ANSI".

+1 pour la rcgmention ci-dessus. C'est toujours mon préféré car il est si simple à personnaliser dans un alias. Quelque chose comme ça se trouve généralement dans mon ~ / .bashrc:

alias tailc = 'tail -f / my / app / log / file | rcg envoyer "BOLD GREEN" recevoir "CYAN" error "RED" '

MarkHu
la source
1

une autre façon sale:

grep -A80 -B80 --color FIND_THIS IN_FILE

J'ai fait un

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

à bashrc.

fly_a320
la source
1
cela est problématique si les choses que vous recherchez ne sont pas là. Dites en raison d'une erreur, auquel cas vous n'obtiendrez rien.
Paul Rubel
0

Si vous souhaitez mettre en évidence plusieurs motifs avec des couleurs différentes, voyez ceci script bash.

Utilisation de base:

echo warn error debug info 10 nil | colog

Vous pouvez modifier les motifs et les couleurs tout en exécutant en appuyant sur une touche, puis sur la touche Entrée.

Edoot
la source
0

J'utilise la commande suivante à des fins similaires:

grep -C 100 searchtext file

Cela indiquera grep pour imprimer 100 * 2 lignes de contexte, avant et après le texte de recherche en surbrillance.

Al Mamun
la source
0

Voici mon approche , inspirée de la solution de @ 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[@]}")
}

Cela accepte plusieurs arguments (mais ne vous permet pas de personnaliser les couleurs). Exemple:

$ noisy_command | highlight ERROR WARN
dimo414
la source
-1

Existe-t-il un moyen de dire à grep d'imprimer chaque ligne en cours de lecture, qu'il y ait ou non une correspondance?

L'option -C999fera l'affaire en l'absence d'une option pour afficher toutes les lignes de contexte. La plupart des autres variantes de grep le supportent également. Cependant: 1) aucune sortie n'est produite lorsqu'aucune correspondance n'est trouvée et 2) cette option a un impact négatif sur l'efficacité de grep: lorsque la -Cvaleur est grande, de nombreuses lignes peuvent devoir être temporairement stockées en mémoire pour grep afin de déterminer quelles lignes de contexte à afficher lorsqu'une correspondance se produit. Notez que les implémentations grep ne chargent pas les fichiers d'entrée mais lisent plutôt quelques lignes ou utilisent une fenêtre glissante sur l'entrée. La "partie avant" du contexte doit être conservée dans une fenêtre (mémoire) pour sortir les lignes de contexte "avant" plus tard lorsqu'une correspondance est trouvée.

Un motif tel que ^|PATTERNou PATTERN|$ou n'importe quel sous-motif de correspondance vide pour cette question comme [^ -~]?|PATTERNest une bonne astuce. Cependant, 1) ces modèles ne montrent pas de lignes non correspondantes mises en évidence comme contexte et 2) cela ne peut pas être utilisé en combinaison avec d'autres options grep, telles que -Fet -wpar exemple.

Donc, aucune de ces approches ne me satisfait. J'utilise ugrep et grep amélioré avec option -ypour afficher efficacement toutes les sorties non correspondantes sous forme de lignes de contexte surlignées en couleur. D'autres outils de type grep tels que ag et ripgrep offrent également une option d'intercommunication. Mais ugrep est compatible avec GNU / BSD grep et offre un sur-ensemble d'options grep comme -yet -Q. Par exemple, voici ce que l'option -yaffiche lorsqu'elle est combinée avec -Q(interface utilisateur de requête interactive pour saisir des modèles):

ugrep -Q -y FILE ...
Dr. Alex RE
la source
Pourquoi voter contre sans laisser de commentaire? Il est plus que juste de mentionner des outils grep alternatifs, comme certaines des autres réponses.
Dr Alex RE