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?

Mark Harrison
fuente
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.

Pat Notz
fuente
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).

Stu
fuente
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.

elmarco
fuente
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.

dbr
fuente
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
Sam Merrell
fuente
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
Chiel ten Brinke
fuente
¿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;
Malcolm Boekhoff
fuente
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.

kenorb
fuente
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.

kenorb
fuente
4
$ grep thestring thefile -5

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

JBone
fuente
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

principal
fuente
1

Yo solía hacerlo de forma compacta

grep -5 string file

Eso es el equivalente de

grep -A 5 -B 5 string file
franzisk
fuente
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
Rosa
fuente