Grep multicolore

J'essaye d'get chaque command de grep pour mettre en évidence ses résultats dans une couleur différente. Je peux le faire manuellement avec une ligne comme ceci:

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 

Chaque caractère c sera surligné en vert et chaque caractère sera surligné en rouge, etc …

Pour que cet exemple fonctionne, vous devez vous assurer que vous avez toujours --color=always sur vos commands grep. J'ai mis ceci dans mon .bashrc donc grep aura toujours des colors:

export GREP_OPTIONS='--color=always'


Ce que je tente d'accomplir est d'envelopper cette fonctionnalité avec un alias, donc je peux juste appeler grep et avoir une valeur GREP_COLORS différente à chaque fois. Je comprends la prise en count de plusieurs shells pour chaque nouveau file grep et j'essaie de le faire en créant des files (un pour chaque couleur) pour indiquer qu'ils ont déjà été utilisés.

J'ai fait quelques tentatives mais étrangement, celui-ci semble fonctionner le "meilleur". J'ai ceci dans mon .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 "$@" } 

J'utilise cet alias comme ceci:

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

Les résultats sont plutôt cool. Il y a cependant quelques erreurs légèrement différentes à chaque fois. Voici quelques captures d'écran:

On dirait que le shell passe par chaque command de pipe, la fonction précédente n'a pas encore fini son exécution. Il tente de supprimer les files qui n'existent plus. Je ne suis pas sûr de savoir d'où viennent ces autres erreurs de command not found .

Comme vous pouvez le voir, j'ai mis quelques commands d' wait pour essayer de terminer la manipulation du file, mais cela ne semble pas fonctionner correctement. Une autre chose que j'ai déjà essayée est d'utiliser la memory partagée /dev/shm mais cela a donné des résultats similaires.

Comment puis-je get les résultats que je veux?

Remarque:

Je cherche des réponses qui emballent simplement la command grep car elle a beaucoup de fonctionnalités que je veux utiliser et j'ai l'intention d'insert une autre logique entre les pipes, donc je ne veux pas fournir tous les termes de search à la fois. Je ne cherche pas non plus d'autres outils "grep like". Désolé pour @terdon qui a déjà posté une suggestion perl génial.

Chaque invocation de grep dans un pipe s'exécute dans un shell séparé, vous devrez donc passer un certain état entre eux. La solution suivante est un moyen brut de gérer cela avec un file qui garde l'index de couleur et un file de locking qui garantit que les appels simultanés ne lisent pas la même valeur:

 #!/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 "$@" 

Testez en supposant que vous avez nommé votre copy cgrep et le mettre sur votre PATH :

 echo foobarbaz | cgrep foo | cgrep bar | cgrep baz 

Voici une approche différente. J'ai un petit script Perl que j'ai déjà posté dans une autre réponse qui mettra en évidence les templates fournis par l'user dans différentes colors. Une version légèrement modifiée du script agira comme grep :

 #!/usr/bin/env perl use Getopt::Std; use ssortingct; 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; } 

Si vous enregistrez ce script en tant que cgrep quelque part dans votre PATH et le rendre exécutable, vous pouvez spécifier jusqu'à 10 motifs différents, dont chacun sera imprimé dans une couleur différente:

entrer la description de l'image ici

 $ 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; 

Si vous êtes bon avec des expressions régulières, vous voudrez peut-être consulter grc et grcat. grc appelle grcat.

grcat utilise des files de configuration dans lesquels vous pouvez append des expressions régulières pour correspondre au text à afficher dans chaque couleur. Il a également un certain nombre d'autres options. Il utilise par défaut la colorisation des files journaux du système.

En fonction de ce que vous avez en tête pour votre script final, vous pouvez colorier votre sortie avec une seule command.

L'astuce est de spécifier les expressions rationnelles correctement pour chaque «champ» dans votre source de données. Ce sera beaucoup plus facile si vos données sont de structure relativement uniforme.

La dernière fois que je l'ai essayé, je ne suis pas allé trop loin, mais je vais peut-être y aller parce que je suis un peu mieux sur les regexes que je ne l'étais à l'époque.

Il y a aussi la command tput qui peut être utilisée pour envoyer des informations (comme les changements de couleur) directement sur votre terminal.

Les deux approches sont couvertes par le post ci-dessous. Il parle de la command find, mais il peut être appliqué à la sortie de n'importe quelle command.

Couleur FIND sortie?