Tengo un archivo con aproximadamente 30.000.000 de líneas (contabilidad de radio) y necesito encontrar la última coincidencia de un patrón dado.
El comando:
tac accounting.log | grep $pattern
da lo que necesito, pero es demasiado lento porque el sistema operativo primero tiene que leer todo el archivo y luego enviarlo a la tubería.
Entonces, necesito algo rápido que pueda leer el archivo desde la última línea hasta la primera.
fuente

tac, mi punto es que no ayuda a menos que también lo use,-mya que el archivo aún necesita ser leído por dos programas. De lo contrario, podría buscar todas las ocurrencias y quedarse solo con la última como hago contail -n 1.grep -m, debería ser bastante eficiente.grep -mél es. El OP no estaba usando,-masí que grep y tac estaban procesando todo.awklínea?La razón por la cual
no se detiene en el primer partido es debido al almacenamiento en búfer.
Normalmente,
head -n 1sale después de leer una línea. Porgreplo tanto, debe obtener un SIGPIPE y salir tan pronto como escriba su segunda línea.Pero lo que sucede es que debido a que su salida no va a una terminal, la
grepamortigua. Es decir, no lo está escribiendo hasta que se haya acumulado lo suficiente (4096 bytes en mi prueba con GNU grep).Lo que eso significa es que
grepno saldrá antes de que haya escrito 8192 bytes de datos, por lo que probablemente bastantes líneas.Con GNU
grep, puede hacer que salga antes usando--line-bufferedel comando que le dice que escriba líneas tan pronto como se encuentren, independientemente de si va a un terminal o no. Entoncesgrepsaldría sobre la segunda línea que encuentra.Pero de
greptodos modos, con GNU , puede usar-m 1en su lugar como ha demostrado @terdon, que es mejor ya que sale en la primera coincidencia.Si tu
grepno es el GNUgrep, entonces puedes usarsedo en suawklugar. Pero altacser un comando GNU, dudo que encuentres un sistema contacdondegrepno sea GNUgrep.Algunos sistemas tienen
tail -rque hacer lo mismo que GNUtac.Tenga en cuenta que, para archivos normales (buscables),
tacytail -rson eficientes porque leen los archivos al revés, no solo leen el archivo completamente en la memoria antes de imprimirlo hacia atrás (como lo haría el enfoque sed de @ slm otacen archivos no regulares) .En sistemas donde ni
tacnitail -restán disponibles, las únicas opciones son implementar la lectura hacia atrás a mano con lenguajes de programación comoperlo usar:O:
Pero eso significa encontrar todas las coincidencias y solo imprimir la última.
fuente
Aquí hay una posible solución que encontrará la ubicación de la primera aparición del patrón desde la última:
Esto hace uso de los interruptores
-sy-rde lostaccuales son los siguientes:fuente
Usando sed
Mostrando algunos métodos alternativos a la excelente respuesta de @ Terdon usando
sed:Ejemplos
Usando Perl
Como beneficio adicional, aquí hay una notación un poco más fácil de recordar en Perl:
Ejemplo
fuente
sedprobable que (especialmente el uno) sea varios órdenes de magnitud más lento quegrep 5 | tail -n1osed '/5/h;$!d;g'. Potencialmente, también utilizará mucha memoria. No es mucho más portátil ya que todavía estás usando GNUgrep -m.