Estou procurando uma maneira de procurar um padrão de várias linhas em um arquivo.
Por exemplo, digamos que esta lista de números seja meu arquivo de entrada:
3
2
5
4
8
2
5
4
2
4
2
5
4
Se eu quisesse pesquisar instâncias das linhas 2-4 (inclusive), gostaria que o resultado fosse:
3
Uma vez que essa é a quantidade de vezes que essas linhas específicas são repetidas exatamente. Eu também gostaria que isso funcionasse com qualquer quantidade de linhas, bem como qualquer intervalo de números de linha no arquivo.
Você pode usar pcregrep , que está disponível na maioria das distribuições. O comando a seguir corresponde a uma string fixa.
Explicação
Na página man, pcregrep é "um grep com expressões regulares compatíveis com Perl".
-M
: corresponde ao regex em várias linhas-c
: exibe o número de correspondências (contagem), em vez das próprias correspondências^2\n5\n4$
: regex para 2, 5, 4, cada um em uma linha separada.Padrão de linhas específicas em vez disso
Comentários posteriores na pergunta sugerem que o padrão a ser correspondido não é uma string fixa, mas sim uma "linhas 2 a 4" geral. Aqui, você pode usar a substituição de comando para analisar as linhas do arquivo de entrada.
Explicação
tail -n+2 input.txt
: saída do arquivo, da linha 2 inclusivehead -n3
: saída apenas as três primeiras linhas\Q...\E
: cite a...
parte para uma correspondência de string básica em oposição à correspondência de regexp (supõe que a saída do comando não contenha\E
).Observe que ele assume que as últimas linhas da saída de
sed ... input.txt
não estão vazias, pois a substituição do comando ($(...)
) remove todos os caracteres de nova linha à direita.Trabalhando:
-0777
=> modo slurp, ou seja, leia o arquivo inteiro.-p
=> antes de ler o próximo registro, imprima o registro atual,$_
para stdout.-l
=> defina o RS = ORS = "\n"/^2\n5\n4$/mg
é aplicado implicitamente no$_
, que no nosso caso é o arquivo inteiro, lembre-se. o/m
modificador regex deve corresponder aos finais e inícios de linha, além dos inícios e finais da string./g
modificador obterá todas as correspondências no$_
arquivo inteiro.HTH
Sua postagem não menciona nenhum requisito para suporte a expressões regulares, então vou assumir que você estará procurando por strings de texto literais e fixas.
Este provavelmente não é o algoritmo mais rápido que você já viu, mas funciona, se você tiver tempo suficiente. Ele tem o pequeno defeito de que, se houver mais de um padrão de linha N que comece com a mesma primeira linha e tenha o mesmo hash SHA256, ele dará resultados incorretos. Ele assume que todos os padrões de linhas N possíveis terão hashes SHA256 exclusivos.
Ele será tedioso em arquivos grandes, especialmente aqueles que contêm várias ocorrências da primeira linha do padrão.
A saída:
Requerimento:
O segundo argumento deve ser pelo menos igual ou maior que o primeiro argumento. Eu não garanto a saída se você violar isso.
Isenção de responsabilidade:
Isso não funciona se os caracteres
\
e/ou$
aparecerem em qualquer uma das linhas incluídas como padrão.awk
se esforça para processar esses caracteres como partes de um padrão, mesmo que tenham escape de barra invertida.Que tal
Com o separador à sua escolha....
Você precisa do regex para evitar uma correspondência no caso de ....
22 5 44
... ou similar