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,-m
ya 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,-m
así que grep y tac estaban procesando todo.awk
línea?La razón por la cual
no se detiene en el primer partido es debido al almacenamiento en búfer.
Normalmente,
head -n 1
sale después de leer una línea. Porgrep
lo 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
grep
amortigua. 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
grep
no 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-buffered
el comando que le dice que escriba líneas tan pronto como se encuentren, independientemente de si va a un terminal o no. Entoncesgrep
saldría sobre la segunda línea que encuentra.Pero de
grep
todos modos, con GNU , puede usar-m 1
en su lugar como ha demostrado @terdon, que es mejor ya que sale en la primera coincidencia.Si tu
grep
no es el GNUgrep
, entonces puedes usarsed
o en suawk
lugar. Pero altac
ser un comando GNU, dudo que encuentres un sistema contac
dondegrep
no sea GNUgrep
.Algunos sistemas tienen
tail -r
que hacer lo mismo que GNUtac
.Tenga en cuenta que, para archivos normales (buscables),
tac
ytail -r
son 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 otac
en archivos no regulares) .En sistemas donde ni
tac
nitail -r
están disponibles, las únicas opciones son implementar la lectura hacia atrás a mano con lenguajes de programación comoperl
o 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
-s
y-r
de lostac
cuales 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
sed
probable que (especialmente el uno) sea varios órdenes de magnitud más lento quegrep 5 | tail -n1
osed '/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
.