Tengo que buscar algunos archivos JSON en los que la longitud de la línea excede algunos miles de caracteres. ¿Cómo puedo limitar grep para mostrar el contexto hasta N caracteres a la izquierda y a la derecha del partido? Cualquier herramienta que no sea grep también estaría bien, siempre que esté disponible en los paquetes comunes de Linux.
Este sería un ejemplo de salida, para el interruptor grep imaginario Ф :
$ grep -r foo *
hello.txt: Once upon a time a big foo came out of the woods.
$ grep -Ф 10 -r foo *
hello.txt: ime a big foo came of t
Respuestas:
Con GNU
grep
:Explicación:
-o
=> Imprime solo lo que hiciste coincidir-P
=> Usar expresiones regulares de estilo Perl$N
caracteresfoo
seguido de 0 seguido por los$N
caracteres.Si no tienes GNU
grep
:Explicación:
Como ya no podemos confiar en
grep
ser GNUgrep
, utilizamosfind
para buscar archivos de forma recursiva (la-r
acción de GNUgrep
). Para cada archivo encontrado, ejecutamos el fragmento de Perl.Interruptores Perl:
-n
Lee el archivo línea por línea-l
Elimine la nueva línea al final de cada línea y vuelva a colocarla al imprimir-e
Trate la siguiente cadena como códigoEl fragmento de Perl está haciendo esencialmente lo mismo que
grep
. Comienza configurando una variable$N
al número de caracteres de contexto que desea. EstoBEGIN{}
significa que esto se ejecuta solo una vez al comienzo de la ejecución, no una vez por cada línea en cada archivo.La instrucción ejecutada para cada línea es imprimir la línea si la sustitución de expresiones regulares funciona.
La expresión regular:
^.*?
) seguido de.{0,$N}
como en elgrep
caso,foo
seguido de otro seguido.{0,$N}
y finalmente haga coincidir cualquier cosa vieja perezosamente hasta el final de la línea (.*?$
).$ARGV:$1
.$ARGV
es una variable mágica que contiene el nombre del archivo actual que se está leyendo.$1
es lo que emparejaron los padres: el contexto en este caso.foo
sin fallar (ya que.{0,$N}
se permite que coincidan cero veces).1 Es decir, prefiera no hacer coincidir nada a menos que esto haga que falle la coincidencia general. En resumen, combine la menor cantidad de caracteres posible.
fuente
| grep foo
al final (sin embargo, perdiendo el resaltado del nombre de archivo en el proceso).grep
puede especificar colores / aplicaciones coincidentes basados en indicadores aplicados a través de variables de entorno. así que tal vez incluso podrías ganarlos a todos, (sin promesas, ni siquiera estoy seguro de que funcionaría en este caso) pero personalmente no veo la relevancia aquí ... de todos modos ... sigue jugando.zsh
No puedo hacer que funcione pasando N = 10 como en el ejemplo. Sin embargo, funciona siexport N=10
antes de ejecutar el comando. ¿Alguna idea de cómo ajustar el ejemplo para trabajar con zsh?perl -lne 'print "$ARGV: $_" for /.{0,10}foo.{0,10}/g'
Intenta usar este:
-E dice que quieres usar expresiones regulares extendidas
-o dice que solo quieres imprimir la coincidencia
-r grep busca resultados de forma recursiva en la carpeta
REGEX:
{0,10} indica cuántos caracteres arbitrarios desea imprimir
. representa un carácter arbitrario (un personaje en sí no era importante aquí, solo su número)
Editar: Ah, ya veo, que Joseph recomienda casi la misma solución que yo: D
fuente
-E
es significativamente más rápido que-P
.Tomado de: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/ y https: // stackoverflow. com / a / 39029954/1150462
El enfoque sugerido
".{0,10}<original pattern>.{0,10}"
es perfectamente bueno, excepto que el color de resaltado a menudo está desordenado. He creado un script con una salida similar, pero el color también se conserva:Suponiendo que el script se guarda como
grepl
,grepl pattern file_with_long_lines
debería mostrar las líneas coincidentes pero con solo 10 caracteres alrededor de la cadena coincidente.fuente
Tubería estándar
cut
con la-b
bandera; Puede indicar la salida de grep a solo bytes 1 a 400 por línea.fuente