Adicionando o conteúdo de vários arquivos usando o awk

1

Digamos que eu tenha alguns arquivos chamados file1, file2, file3 , ... que possuem o seguinte formato

arquivo1

blah blah blah
[PATTERN0]
a10
a20
a30
[PATTERN1]
a11
a21
a31
[PATTERN3]
a13
a13
a33

arquivo 2

blah blah blah
[PATTERN0]
b10
b20
b30
[PATTERN1]
b11
b21
b31
[PATTERN3]
b13
b13
b33

O que eu gostaria de fazer é acabar com um arquivo que contenha a soma de cada entrada individual para todos os arquivos após o padrão específico (por exemplo, PATTERN0). Por exemplo, o arquivo deve ter

a10+b10
a20+b20
a30+b30

Até agora só posso rrad e imprimir os valores usando

awk '/PATTERN0/ {for(i=1; i<=3; i++) {getline;print $1}}' file*

Alguma ideia de como fazer isso?

    
por Thanos 27.03.2017 / 17:15

2 respostas

4

Com awk , supondo que você sempre tenha pelo menos dois arquivos, que todos os arquivos tenham o mesmo número de linhas entre [PATTERN0] e [PATTERN1] e que essas linhas sejam na verdade números:

awk '
    BEGIN {
        # discard the garbage before [PATTERN0]
        for (i = 1; i < ARGC; i++) {
            do      
                getline str <ARGV[i]
            while (str !~ /\[PATTERN0\]/)
        }

        # read sum from first file, then add numbers in turn from the other files
        while ((getline sum <ARGV[1]) && sum !~ /\[PATTERN1\]/) {
            for (i = 2; i < ARGC; i++) {
                getline nr <ARGV[i]
                sum += nr
            }
            print sum
        }
    }' file1 file2 file3 ...
    
por 27.03.2017 / 17:45
0

Uma combinação de colar + awk fornece bons resultados:

$ paste -d"+" file1 file2 |awk -F"[+]" '/PATTERN/{print $1;next}1'

Eu chamo o awk para evitar ter [PATTERN0]+[PATTERN0] - você pode removê-lo ou se você não quiser que [PATTERN] seja impresso em todas as alterações no último awk para ...|awk -F"[+]" '/PATTERN/{next}1

Teste:

$ paste -d"+" <(echo "$a") <(echo "$b") |awk -F"[+]" '/PATTERN/{next}1'
a10+b10
a20+b20
a30+b30
a11+b11
a21+b21
a31+b31
a13+b13
a13+b13
a33+b33

Também aqui está uma solução fácil para o awk:

$ awk -v RS="[PATTERN[0-9]+]" '{for (i=1;i<=NF;i++) (NR==FNR)?a[RT][i]=$i:a[RT][i]=a[RT][i] "+" $i} \
END{for (k in a) for (l in a[k]) print a[k][l]}' <(echo "$a") <(echo "$b")

PS: Acima de awk está em uma linha removendo o \ . É dividido em duas linhas apenas para facilitar a leitura aqui.

Pitfall para este awk é que na seção END, a impressão está correta, mas na ordem PATTERN aleatória (ou seja, [PATTERN3] data pode ser impressa primeiro em vez de [PATTERN0] ) devido à maneira como o awk imprime arrays com este método.

    
por 27.03.2017 / 23:28

Tags