Obtener la última coincidencia en un archivo usando grep

58

¿Cuál es la mejor manera de obtener solo la coincidencia final de una expresión regular en un archivo usando grep?

Además, ¿es posible comenzar a grepping desde el final del archivo en lugar del principio y detenerse cuando encuentra la primera coincidencia?

Bellota
fuente

Respuestas:

85

Tu podrías intentar

grep pattern file | tail -1

o

tac file | grep pattern | head -1

o

tac file | grep -m1 pattern
Cakemox
fuente
20
tac file | grep -m 1 pattern
Dennis Williamson el
1
Con la restricción añadida de que quería obtener el número de línea ( grep -n) en el archivo real, creo tacque debía evitarse, a menos que quisiera restarle algo wc -l. De lo contrario tac, con grep -m1tiene mucho sentido.
Nick Merrill
1
Me encantaría ver una versión más eficiente que esta, ya que estoy tratando de buscar un archivo de 20GB.
Jeff
La respuesta de @DennisWilliamson es mucho mejor porque grepdejará de funcionar después del primer partido. sin -m 1, grepprimero encontrará todos los patrones coincidentes en el archivo , luego headmostrará solo el primero, mucho menos eficiente. ¡Dennis, por favor considere publicar esto en una respuesta separada!
gilad mayani
1

Para alguien que trabaja con grandes archivos de texto en Unix / Linux / Mac / Cygwin. Si usa Windows, consulte esto sobre las herramientas de Linux en Windows: https://stackoverflow.com/questions/3519738/what-is-the-best-way-to-use-linux-utilities-under-windows .

Uno puede seguir este flujo de trabajo para tener un buen rendimiento:

  1. comprimir con gzip
  2. use zindex (en github: https://github.com/mattgodbolt/zindex ) para indexar el archivo con la clave adecuada
  3. consultar el archivo indexado con zqel paquete.

Cita de su léame github:

Crear un índice

Es necesario decirle al zindex qué parte de cada línea constituye el índice. Esto puede hacerse mediante una expresión regular, por campo o canalizando cada línea a través de un programa externo.

Por defecto, zindex crea un índice de file.gz.zindex cuando se le pide que indexe file.gz.

Ejemplo:

crear un índice en líneas que coincidan con una expresión regular numérica. El grupo de captura indica la parte que se debe indexar, y las opciones muestran que cada línea tiene un índice numérico único.

$ zindex file.gz --regex 'id:([0-9]+)' --numeric --unique

Ejemplo: crear un índice en el segundo campo de un archivo CSV:

$ zindex file.gz --delimiter , --field 2 

Ejemplo:

cree un índice en un campo JSON orderId.id en cualquiera de los elementos en la matriz de acciones de la raíz del documento (requiere jq). La consulta jq crea una matriz de todos los orderId.ids, luego los une con un espacio para garantizar que cada línea individual canalizada a jq cree una sola línea de salida, con múltiples coincidencias separadas por espacios (que es el separador predeterminado).

$ zindex file.gz --pipe "jq --raw-output --unbuffered '[.actions[].orderId.id] | join(\" \")'" 

Consultando el índice

El programa zq se usa para consultar un índice. Se le da el nombre del archivo comprimido y una lista de consultas. Por ejemplo:

$ zq file.gz 1023 4443 554 

También es posible imprimir por número de línea, por lo que para imprimir las líneas 1 y 1000 desde un archivo:

$ zq file.gz --line 1 1000
biocyberman
fuente
1

Siempre estoy usando cat (pero esto lo hace un poco más largo): cat file | grep pattern | tail -1

Culparía a mi maestro del curso de administración de Linux en la universidad que ama los gatos :))))

- No tiene que atrapar un archivo antes de agarrarlo. grep pattern file | tail -1y es más eficiente también.

Ismail Guneydas
fuente
66
Esta es solo la primera parte de la respuesta de Cakemox, excepto que peor.
augurar
Funciona, pero hace pasos innecesarios. Para un uso ligero, esta solución funciona bien, pero no funciona bien. La razón es porque no necesita catel archivo y canalizarlo grep. Puede grepbuscar el archivo directamente a través de grep pattern file(y luego usarlo tailpara devolver el último resultado), como en la respuesta de Cakemox.
jvriesem