grep un archivo, pero muestra varias líneas circundantes?


3421

Me gustaría greppara una cadena, pero también mostrar las cinco líneas anteriores y las siguientes cinco líneas, así como la línea coincidente. ¿Cómo podría hacer esto?


3
Guardo una copia del script en perl de Brendan Gregg para este propósito. Funciona bien.
Ethan Post

66
Para obtener una solución que funcione en Solaris, consulte este enlace .
jahroy

107
man grep | grep -C 1 context:)
StvnW

20
man grep | grep -C 1 "\-C";)
Anders B

99
@StvnW ... No sé si llamar a ese meta (en un contexto más general, en lugar de SO), o cómo llamarlo. Respondiste la pregunta mostrando cómo usar la respuesta para encontrar la respuesta.
bballdave025

Respuestas:


4540

Para BSD o GNU grep , puede usar -B numpara establecer cuántas líneas antes del partido y -A numpara el número de líneas después del partido.

grep -B 3 -A 2 foo README.txt

Si desea el mismo número de líneas antes y después puede usar -C num.

grep -C 3 foo README.txt

Esto mostrará 3 líneas antes y 3 líneas después.


56
Es bueno, pero desafortunadamente el grep de Solaris no lo admite. Vea ese enlace para solaris: unix.com/solaris/33533-grep-display-few-lines-before-after.html
рüффп

99
Ok, pero ¿y si quieres mostrar todas las líneas de salida después del partido? grep -A0 y grep -A-1 no lo cortan ...
g33kz0r

2
no funciona para mí por alguna razón, aunque se menciona en mis páginas de manual.
Hayri Uğur Koltuk

2
Si tiene HP-UX env, ninguna de las versiones grep funcionará como en Solaris. Pude usar el enlace de Solaris pero reemplacé nawk con awk en ese enlace.
zkarthik el

66
-n es para números de línea, pero para algunas versiones de grep -n # mostrará # líneas circundantes (como -c) con números de línea. Ese es un atajo útil que es mi opción cuando necesito contexto.
Anthony DiSanti

607

-Ay -Bfuncionará, como lo hará -C n(para nlíneas de contexto), o simplemente -n(para nlíneas de contexto ... siempre que n sea 1 a 9).


Probé el -nformato y descubrí que solo funciona hasta 9. Porque 15devuelve 5 líneas
Deepak Mahakale

8
@DeepakMahakale Esto probablemente esté relacionado con la forma en que los programas / opciones POSIX analizan típicamente los argumentos / opciones de la línea de comandos. El especificador de opción es un solo carácter (como -A, -Bo -C). Por lo general, el especificador de opción va seguido de un valor ( -o a.outpara especificar el archivo de salida en GCC), pero también puede funcionar como un simple interruptor / indicador ( -gpara habilitar la información de depuración en GCC). Sin embargo, los espacios entre las opciones son opcionales, por lo que para las opciones sin valor, es posible fusionarlas ( -ABC), lo que significa que -15se interpreta -1 -5(dos opciones separadas) y se -5anula el -1.
natiiix

1
-5 es más rápido que ambos -A 5 -B 5. Esos no deben usarse juntos. Es más limpio para otros lectores del script si elige -A o -B o -C sobre -9.
Eric Aldinger

77

ack funciona con argumentos similares a grep y acepta -C. Pero generalmente es mejor para buscar a través del código.


55
ack también es compatible con -A -B.
Shuo

Ack es mejor que grep en muchos sentidos. Es más rápido con una sintaxis más simple.
chim

1
Sin embargo, grep tiene la ventaja de estar instalado por defecto en muchos sistemas.
Marc Z

1
@MarcZ: Cierto, es más probable que grep se instale de manera predeterminada que ack, pero ack es un script portátil e independiente. No es necesario compilarlo o instalarlo en un directorio del sistema como / usr / bin /. Una vez que se descarga y se coloca en un directorio listado en $ PATH (y su conjunto de bits de permiso eXecute), debería funcionar de inmediato. (No se requieren privilegios de sudo o root para que el trabajo funcione.)
JL

Esta pregunta se refiere grep, no está seguro de usarlo para "publicitar" ack(que es una gran herramienta, de hecho) es una buena idea ...
MonsieurDart

39
grep astring myfile -A 5 -B 5

Eso marcará "myfile" por "astring" y mostrará 5 líneas antes y después de cada partida.


19
"grep astring myfile -C 5" hará lo mismo
Syed Siraj Uddin

20

Normalmente uso

grep searchstring file -C n # n for number of lines of context up and down

Muchas de las herramientas como grep también tienen archivos man realmente geniales. Me encuentro refiriéndome mucho a la página de manual de grep porque hay mucho que puedes hacer con ella.

man grep

Muchas herramientas de GNU también tienen una página de información que puede tener información más útil además de la página de manual.

info grep

13

Usa grep

$ grep --help | grep -i context
Context control:
  -B, --before-context=NUM  print NUM lines of leading context
  -A, --after-context=NUM   print NUM lines of trailing context
  -C, --context=NUM         print NUM lines of output context
  -NUM                      same as --context=NUM

¿No leíste la respuesta aceptada? Simplemente estás repitiendo lo que ya se ha dicho sobre una pregunta de casi 10 años ...
Yokai

77
Oh lo siento, Yokai. Pero no leo nada sobre grep en la sección de ayuda de grep para recuperar la respuesta.
Chiel ten Brinke

1
@Yokai Además de lo que dijo Chiel ten Brinke, la respuesta aceptada no menciona las opciones largas
usuario3738870

11

Busque "17655" en "/some/file.txt" que muestra el contexto de 10 líneas antes y después (usando Awk), salida precedida por un número de línea seguido de dos puntos. Use esto en Solaris cuando 'grep' no sea compatible con las opciones "- [ACB]".

awk '

/17655/ {
        for (i = (b + 1) % 10; i != b; i = (i + 1) % 10) {
                print before[i]
        }
        print (NR ":" ($0))
        a = 10
}

a-- > 0 {
        print (NR ":" ($0))
}

{
        before[b] = (NR ":" ($0))
        b = (b + 1) % 10
}' /some/file.txt;

7

ripgrep

Si se preocupan por el rendimiento, el uso ripgrepque tiene una sintaxis similar a grep, por ejemplo,

rg -C5 "pattern" .

-C, --context NUM- Muestra NUM líneas antes y después de cada partido.

También hay parámetros como -A/ --after-contexty -B/ --before-context.

La herramienta está construida sobre el motor regex de Rust, lo que lo hace muy eficiente en los datos grandes.


5

Aquí está la solución @Ygor enawk

awk 'c-->0;$0~s{if(b)for(c=b+1;c>1;c--)print r[(NR-c+1)%b];print;c=a}b{r[NR%b]=$0}' b=3 a=3 s="pattern" myfile

Nota: Reemplazar ay bvariables con número de líneas antes y después.

Es especialmente útil para el sistema que no soporta de grep -A, -By -Cparámetros.


4
$ grep thestring thefile -5

-5obtiene 5líneas arriba y abajo del partido 'thestring' es equivalente a -C 5o -A 5 -B 5.


4

Grep tiene una opción llamada Context Line Control, puedes usarla --contexten eso, simplemente,

| grep -C 5

o

| grep -5

Debería hacer el truco


1

Yo solía hacerlo de forma compacta

grep -5 string file

Eso es el equivalente de

grep -A 5 -B 5 string file

0

Si busca código con frecuencia, AG el buscador de plata es mucho más eficiente (es decir, más rápido) que grep.

Muestra líneas de contexto utilizando la opción -C.

P.ej:

ag -C 3 "foo" myFile

line 1
line 2
line 3
line that has "foo"
line 5
line 6
line 7
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.