Obtendo a última correspondência em um arquivo usando grep

58

Qual é a melhor maneira de obter apenas a correspondência final de uma expressão regular em um arquivo usando grep?

Além disso, é possível começar o grepping do final do arquivo em vez do início e parar quando encontrar a primeira correspondência?

Bolota
fonte

Respostas:

85

Você poderia tentar

grep pattern file | tail -1

ou

tac file | grep pattern | head -1

ou

tac file | grep -m1 pattern
Cakemox
fonte
20
tac file | grep -m 1 pattern
Dennis Williamson
11
Com a restrição adicional de que eu queria obter o número da linha ( grep -n) no arquivo real, acho que tacpraticamente tive que ser evitado, a menos que quisesse fazer uma subtração wc -l. Caso contrário, taccom grep -m1faz muito sentido.
59904 Nickelillill
11
Eu adoraria ver uma versão com melhor desempenho do que essa, pois estou tentando pesquisar um arquivo de 20 GB.
Jeff Jeff
A resposta de @DennisWilliamson é muito melhor porque grepdeixará de funcionar após a primeira partida. sem -m 1, grepprimeiro encontrará todos os padrões correspondentes no arquivo e depois headmostrará apenas o primeiro - muito menos eficiente. Dennis, considere postar isso em uma resposta separada!
gilad Mayani
1

Para alguém que trabalha com grandes arquivos de texto em Unix / Linux / Mac / Cygwin. Se você usa o Windows, verifique isso sobre as ferramentas Linux no Windows: https://stackoverflow.com/questions/3519738/what-is-the-best-way-to-use-linux-utilities-under-windows .

Pode-se seguir este fluxo de trabalho para obter um bom desempenho:

  1. comprimir com gzip
  2. use zindex (no github: https://github.com/mattgodbolt/zindex ) para indexar o arquivo com a chave apropriada
  3. consulte o arquivo indexado zqno pacote.

Cite seu leia-me no github:

Criando um índice

O zindex precisa ser informado sobre qual parte de cada linha constitui o índice. Isso pode ser feito por uma expressão regular, por campo ou canalizando cada linha por meio de um programa externo.

Por padrão, o zindex cria um índice de file.gz.zindex quando solicitado a indexar file.gz.

Exemplo:

crie um índice nas linhas correspondentes a uma expressão regular numérica. O grupo de captura indica a parte a ser indexada e as opções mostram que cada linha tem um índice numérico exclusivo.

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

Exemplo: crie um índice no segundo campo de um arquivo CSV:

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

Exemplo:

crie um índice em um campo JSON orderId.id em qualquer um dos itens na matriz de ações da raiz do documento (requer jq). A consulta jq cria uma matriz de todos os orderId.ids e os une a um espaço para garantir que cada linha individual canalizada para jq crie uma única linha de saída, com várias correspondências separadas por espaços (que é o separador padrão).

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

Consultando o índice

O programa zq é usado para consultar um índice. É dado o nome do arquivo compactado e uma lista de consultas. Por exemplo:

$ zq file.gz 1023 4443 554 

Também é possível imprimir pelo número da linha, para imprimir as linhas 1 e 1000 a partir de um arquivo:

$ zq file.gz --line 1 1000
biocibernético
fonte
1

Eu estou sempre usando o gato (mas isso o torna um pouco mais longo): cat file | grep pattern | tail -1

Eu culparia meu professor de curso de administração linux na faculdade que ama gatos :))))

- Você não precisa criar um arquivo antes de cumprimentá-lo. grep pattern file | tail -1e é mais eficiente também.

Ismail Guneydas
fonte
6
Esta é apenas a primeira parte da resposta da Cakemox, exceto pior.
augurar
Funciona, mas executa etapas desnecessárias. Para uso leve, esta solução funciona bem, mas não apresenta um bom desempenho. O motivo é porque você não precisa fazer cato arquivo e canalizá-lo grep. Você pode greppesquisar o arquivo diretamente via grep pattern file(e depois usar tailpara retornar o último resultado), como na resposta da Cakemox.
jvriesem 26/07