leu padrões do arquivo1 e os pesquisou iterativamente no arquivo2

1

Gostaria de ler padrões do arquivo1 e pesquisá-los iterativamente no arquivo2, imprimindo a linha combinada mais 3 linhas e imprimi-los no arquivo3.

Agora estou fazendo:

cat file1 | while read line; do awk '/$line/ {for(i=1; i<=3; i++) {getline; print}}' file2 > file3 ; done

Existe alguma maneira mais eficiente de fazer isso? Meus arquivos irl são bem grandes (~ 30GB)

    
por dovah 09.07.2016 / 19:59

1 resposta

2

Você digitaliza o arquivo uma vez para cada padrão. Seria muito mais rápido passar pelo arquivo apenas uma vez, especialmente porque o arquivo não cabe no cache.

Seu código de amostra, na verdade, salva apenas as correspondências do último padrão em file1 . Eu suponho que isso seja uma simplificação excessiva. Se você precisar de todas as correspondências em um único arquivo, é como se os padrões estivessem unidos ao operador “ou”.

awk '
    BEGIN {
        while (getline <"file1") pattern = pattern "|" $0;
        pattern = substr(pattern, 2);
    }
    match($0, pattern) {for(i=1; i<=3; i++) {getline; print}}
' file2 > file3

Note também que isto não imprime a linha correspondente, apenas as três linhas seguintes. Se você realmente quisesse imprimir a linha correspondente antes das três linhas seguintes, você precisa de um print; adicional antes do loop for .

Se você realmente quisesse imprimir a linha correspondente antes das três linhas a seguir, e seu comando grep suportasse o argumento -A , então você deveria usar isto. Um programa especializado como o grep é geralmente mais rápido que uma linguagem interpretada como o awk. Como um bônus adicional, o comando é muito mais simples.

grep -A -E -f file1 file2 >file3

Se você descobriu que grep é mais lento, pode ser porque você encontrou um defeito do GNU grep em localidades multibyte: às vezes pode ser muito lento, mesmo quando nem o arquivo nem o padrão contiverem caracteres multibyte. Se você não estiver usando classes de caracteres para corresponder a caracteres não-ASCII (por exemplo, você não usa [[:alpha:]] para corresponder a todas as letras Unicode), execute grep em uma localidade unibyte:

LC_ALL=C grep -A3 -E -f file1 file2 >file3

A saída do grep não é exatamente a mesma do snippet awk, porque eles se comportam de maneira diferente se o padrão for encontrado em uma das linhas sendo impressas devido a uma linha anterior. Por exemplo, se o padrão for a e as linhas forem a1 , a2 , b , c , d então grep -A3 imprime a1 , a2 , b , c , enquanto o snippet de awk acima imprime a2 , b , c e o fragmento de awk com o% adicional print imprime a1 , a2 , b , c .

    
por 10.07.2016 / 02:00