Grep coloreado: ver el archivo completo con coincidencias resaltadas

509

Encuentro que grepla --color=alwaysbandera es tremendamente útil. Sin embargo, grep solo imprime líneas con coincidencias (a menos que solicite líneas de contexto). Dado que cada línea que imprime tiene una coincidencia, el resaltado no agrega tanta capacidad como podría.

Realmente me gustaría catun archivo y ver todo el archivo con las coincidencias de patrón resaltadas.

¿Hay alguna manera de decirle a grep que imprima cada línea que se lee independientemente de si hay una coincidencia? Sé que podría escribir un script para ejecutar grep en cada línea de un archivo, pero tenía curiosidad por saber si esto era posible con el estándar grep.

zslayton
fuente
1
si desea más de un color para más de un patrón (es decir, mensajes de error, advertencia, información, etc.), usesed . la sedsolución le ofrece múltiples colores a costa de una mayor complejidad (en lugar de unos 30 caracteres, tiene unos 60 caracteres).
Trevor Boyd Smith
Con sed , incluso puede resaltar + regresar el código de salida , ver ejemplo: askubuntu.com/a/1200851/670392
Noam Manos

Respuestas:

797

Aquí hay algunas formas de hacerlo:

grep --color -E 'pattern|$' file
grep --color 'pattern\|$' file
egrep --color 'pattern|$' file
Ryan Oberoi
fuente
152
¡Ese truco es genial! Bien hecho, tendré que recordar eso. Para aquellos de ustedes que no son expertos en expresiones regulares, "patrón | $" coincidirá con las líneas que tienen el patrón que está buscando Y las líneas que tienen un final, es decir, todas ellas. Debido a que el final de una línea no tiene ningún carácter, la parte coloreada de la salida será solo su patrón. Gracias Ryan!
zslayton
55
También puede omitir el "$": egrep --color "pattern|" file(credit stackoverflow.com/a/7398092/50979 )
13ren
15
@Zack, el "|" operador es un operador OR, no un AND,
JBoy
16
@JBoy, estaba usando 'AND' en la forma convencional en inglés en lugar de la lógica booleana. Estás en lo cierto, de hecho es un operador 'o': coincide con esto y aquello. : P Buena aclaración.
zslayton
12
Parece que se necesita el "$" si coincide con más de un patrón. egrep --color "pattern1|pattern2|$". De lo contrario, no se resalta el color.
ZaSter
91

Aquí hay algo en la misma línea. Lo más probable es que use menos de todos modos, así que intente esto:

less -p pattern file

Destacará el patrón y saltará a la primera aparición del mismo en el archivo.

Pausado hasta nuevo aviso.
fuente
44
También funciona con tuberías (lectura desde stding) usando -:… | less -p pattern -
phk
3
@phk: Incluso puedes omitir el guión.
Pausado hasta nuevo aviso.
Además, agregar la -iopción hará que la coincidencia sea insensible como en less -ip pattern file.
steveb
... y si la tubería está en entrada de color ANSI, proporcione lessel -Rinterruptor:… | less -Rip introduction -
Abdull
48

Me gustaría recomendar ack, mejor que grep, una herramienta de búsqueda poderosa para programadores .

$ ack --color --passthru --pager = "$ {PAGER: -less -R}" archivos de patrones
$ ack --color --passthru archivos de patrones | menos -R
$ export ACK_PAGER_COLOR = "$ {PAGER: -less -R}"
$ ack --passthru archivos de patrones

Me encanta porque el valor predeterminado es la búsqueda recursiva de directorios (y es mucho más inteligente que grep -r), admite expresiones regulares completas de Perl (en lugar de POSIXish regex(3)) y tiene una visualización de contexto mucho más agradable al buscar muchos archivos.

efímero
fuente
2
Sin embargo, de vez en cuando, no encuentra lo que quiero cuando estoy seguro de que debe estar allí. ackes inteligente, pero a veces demasiado inteligente, y excluía el tipo de archivo en el que estaba el golpe.
Michael Piefel
44
@MPi ack -abuscará todos los tipos de archivos, mientras que aún excluyendo .git/ .svn/etc.
ephemient
1
Sin embargo, es genial que ackno busque a través de mis imágenes, también lo -ahace demasiado. Agregué --type-set=freemarker=.ftla mi ~/.ackrc, para dar un ejemplo.
Michael Piefel
3
Con algunos ajustes de configuración, grep ya hace todo lo que hace ack, es más rápido y nunca omite resultados como lo hacen a veces las listas blancas de ack. Quizás guarde su configuración grep preferida en .bashrc. Lecturas mías: función grp () {GREP_OPTIONS = "- rI --color --exclude-dir = \. Git --exclude = tags" grep "$ @"
Jonathan Hartley

22

Puedes usar mi highlightscript desde https://github.com/kepkin/dev-shell-essentials

Es mejor que grepporque puedas resaltar cada partido con su propio color .

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

Captura de pantalla del proyecto Github


3
La pregunta solicitó expresamente una solución usando grep, que es una utilidad estándar en máquinas que ejecutan * nix.
zslayton

1
Este script es bueno, pero no tan bueno como se coloutmenciona en otra respuesta.
Jonathan Hartley

@ JonathanHartley ¿Y por qué es así? No veo razón para ello. Además, este script utiliza una implementación mucho más simple que colout, lo cual es bueno si desea inspeccionar lo que hace.
Hola

@HelloGoodbye Sí, lo suficientemente justo. Debería aplazar el juicio. colout es más completo y potente, pero tiene razón en que es correspondientemente más complejo de usar y realizar ingeniería inversa.
Jonathan Hartley

@ JonathanHartley ¡Tiene sentido que sea más poderoso!
Hola

19

También puedes crear un alias. Agregue esta función en su .bashrc (o .bash_profile en osx)

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

Ahora puede usar el alias de esta manera: " ifconfig | grepe inet" o " grepe css index.html".

(PD: no olvides source ~/.bashrcvolver a cargar bashrc en la sesión actual)


también puede usar solo use egrep si está disponible en su sistema.
Tom

1
La canalización del resultado de esto a menos pierde la información de color. ¿Cómo evitarías eso?
Connor Clark

55
Uso @Hoten en --color=alwayslugar de--color
limp_chimp

3
Y, para lessinterpretar los códigos de color, use less -R.
Eliah Kagan

El uso no cotizado de $ 2 no es seguro en blanco. En una fiesta preferiría hacer la función grepe () {patrón local = "$ 1" shift egrep --color "$ patrón | ^" "$ @"} Perdón por el desorden de formato.
Robert Klemme
16

Utilice el coloutprograma: http://nojhan.github.io/colout/

Está diseñado para agregar resaltados de color a una secuencia de texto. Dado una expresión regular y un color (por ejemplo, "rojo"), reproduce una secuencia de texto con coincidencias resaltadas. p.ej:

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

Puede encadenar varias invocaciones para agregar múltiples resaltados de colores diferentes:

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

O puede lograr lo mismo utilizando una expresión regular con N grupos (partes entre paréntesis de la expresión regular), seguida de una lista de N colores separados por comas.

vagrant status | \
    colout \
        '\''(^.+  running)|(^.+suspended)|(^.+not running)'\'' \
        green,yellow,red
usuario2683246
fuente
1
Como se señaló en otra parte, la pregunta solicitó expresamente una solución usando grep, que es una utilidad estándar en máquinas que ejecutan * nix.
zslayton
44
@Zack ok, lo siento. En realidad, si expande el problema más allá grep, y ya está expandido en las respuestas, coloutes la mejor solución para el problema que tuvo, lo mejor que sé. Según la filosofía de UNIX, los programas deben escribirse para hacer una cosa bien. Porque grepestá filtrando flujo de texto. Porque coloutestá coloreando o resaltando la secuencia de texto.
user2683246
Esta es la mejor respuesta, ya que puede aplicar múltiples resaltados de diferentes colores, y coloutes una herramienta muy útil. Aprenda una vez, úsela en muchas situaciones, en lugar de aprender una herramienta para resaltar archivos de registro, otra para resaltar el resultado de la prueba, etc.
Jonathan Hartley
9

Yo uso rcg de "Linux Server Hacks", O'Reilly. Es perfecto para lo que desea y puede resaltar múltiples expresiones, cada una con diferentes colores.

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

¡La -zopción para grep también es bastante hábil!

cat file1 | grep -z "pattern"
Abhishek Jaisingh
fuente
¿Qué hace esto? -z le dice a grep que use ASCII NUL como delimitador de línea ...
vy32
6

Agregué esto a mis .bash_aliases:

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

Para resaltar patrones mientras ve el archivo completo, h puede hacer esto.

Además, utiliza diferentes colores para diferentes patrones.

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

También puede canalizar la salida de ha less -Rpara una mejor lectura.

Para grep y usar 1 color para cada patrón, cxpgrep podría ser una buena opción .

treulz
fuente
1

Ok, esta es una forma

wc -l filename

le dará el recuento de líneas - diga NN, luego puede hacer

grep -C NN --color=always filename
nik
fuente
3
"-C 2147483647" si no desea wc primero. Usar un número grande aquí no parece ralentizar las cosas.
barrycarter
1

Aquí hay un script de shell que utiliza la función gsub de Awk para reemplazar el texto que está buscando con la secuencia de escape adecuada para mostrarlo en rojo brillante:

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

Úselo así:

$ ./cgrep pattern [file]

Desafortunadamente, no tiene toda la funcionalidad de grep.

Para obtener más información, puede consultar un artículo " So You Like Color " en Linux Journal

Wernsey
fuente
1

Otra respuesta mencionó el interruptor grep's -Cn que incluye n líneas de contexto. A veces hago esto con n = 99 como una forma rápida y sucia de obtener [al menos] una pantalla llena de contexto cuando el patrón egrep parece demasiado complicado, o cuando estoy en una máquina en la que no he instalado rcg y / o ccze.

Recientemente descubrí cczecuál es un colorante más potente. Mi única queja es que está orientado a la pantalla (como less, que nunca uso por ese motivo) a menos que especifique el interruptor -A para la salida "ANSI sin procesar".

+1 por la rcgmención anterior. Sigue siendo mi favorito, ya que es muy sencillo de personalizar en un alias. Algo así suele estar en mi ~ / .bashrc:

alias tailc = 'tail -f / my / app / log / file | rcg envía "VERDE NEGRO" recibe el error "CIAN" "ROJO"

MarkHu
fuente
1

Otra forma sucia:

grep -A80 -B80 --color FIND_THIS IN_FILE

Hice un

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

en bashrc.

fly_a320
fuente
1
Esto es problemático si las cosas que estás buscando no están allí. Diga debido a un error, en cuyo caso no obtendrá nada.
Paul Rubel
0

Si desea resaltar varios patrones con diferentes colores, vea este script bash.

Uso básico:

echo warn error debug info 10 nil | colog

Puede cambiar patrones y colores mientras se ejecuta presionando una tecla y luego ingresar la tecla.

Edoot
fuente
0

Yo uso el siguiente comando para un propósito similar:

grep -C 100 searchtext file

Esto dirá grep para imprimir 100 * 2 líneas de contexto, antes y después del texto de búsqueda resaltado.

Al Mamun
fuente
0

Aquí está mi enfoque , inspirado en la solución 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[@]}")
}

Esto acepta múltiples argumentos (pero no le permite personalizar los colores). Ejemplo:

$ noisy_command | highlight ERROR WARN
dimo414
fuente
-1

¿Hay alguna manera de decirle a grep que imprima cada línea que se lee independientemente de si hay una coincidencia?

La opción -C999hará el truco en ausencia de una opción para mostrar todas las líneas de contexto. La mayoría de las otras variantes de grep también admiten esto. Sin embargo: 1) no se produce salida cuando no se encuentra ninguna coincidencia y 2) esta opción tiene un impacto negativo en la eficiencia de grep: cuando el -Cvalor es grande, es posible que muchas líneas deban almacenarse temporalmente en la memoria para que grep determine qué líneas de contexto para mostrar cuando se produce una coincidencia. Tenga en cuenta que las implementaciones de grep no cargan archivos de entrada, sino que leen algunas líneas o usan una ventana deslizante sobre la entrada. La "parte anterior" del contexto debe mantenerse en una ventana (memoria) para generar las líneas de contexto "anterior" más adelante cuando se encuentra una coincidencia.

Un patrón como ^|PATTERNo PATTERN|$cualquier subpatrón de coincidencia vacía para ese asunto [^ -~]?|PATTERNes un buen truco. Sin embargo, 1) estos patrones no muestran líneas no coincidentes resaltadas como contexto y 2) esto no se puede usar en combinación con algunas otras opciones grep, como -Fy -wpor ejemplo.

Así que ninguno de estos enfoques me satisface. Estoy usando ugrep y grep mejorado con la opción -yde mostrar de manera eficiente todos los resultados no coincidentes como líneas de contexto resaltadas en color. Otras herramientas similares a grep como ag y ripgrep también ofrecen una opción de transferencia. Pero ugrep es compatible con GNU / BSD grep y ofrece un superconjunto de opciones grep como -yy -Q. Por ejemplo, esto es lo que -ymuestra la opción cuando se combina con -Q(interfaz de usuario de consulta interactiva para ingresar patrones):

ugrep -Q -y FILE ...
Dr. Alex RE
fuente
¿Por qué votar esto sin dejar un comentario? Es más que justo mencionar herramientas alternativas de grep, al igual que algunas de las otras respuestas.
Dr. Alex RE