
Gostaria muito de receber sua ajuda. Estou extraindo informações de arquivos de dados que, em alguns casos, têm mais de um terabyte de tamanho.
- As variáveis em cada linha são separadas por espaços em branco.
- A quantidade de variáveis em cada linha é fixa para cada arquivo
- Três colunas à direita sempre números naturais
- As linhas sempre começam com um array
- Arrays sempre contêm uma quantidade fixa de elementos por arquivo
- Matrizes podem conter de 1 a 5 elementos
- O arquivo de dados de origem está classificado corretamente
O exemplo abaixo compara uma matriz de três elementos com todas as outras matrizes no arquivo ou bloco ao usar paralelo. Se a matriz corresponder, a segunda coluna da direita será adicionada e as linhas serão mescladas. A coluna mais à direita e a coluna -2 são liberadas.
g@grml # zcat googlebooks-eng-us-all-3gram-20120701-zz.gz | head
Z'Z . _END_ 1840 1 1
Z'Z . _END_ 1847 1 1
Z'Z . _END_ 1850 1 1
Z'Z . _END_ 1855 1 1
Z'Z . _END_ 1856 1 1
Z'Z . _END_ 1857 1 1
Z'Z . _END_ 1860 1 1
Z'Z . _END_ 1863 1 1
Z'Z . _END_ 1865 1 1
Z'Z . _END_ 1869 1 1
g@grml # zcat googlebooks-eng-us-all-3gram-20120701-zz.gz | parallel -k -q --pipe awk '{a[$1" "$2" "$3] +=$(NF-1)} END{for (i in a) print i, a[i]}' | head
Zz_NOUN _NOUN_ , 98
zz _._ _PRT_ 120
ZZ or_CONJ _NOUN_ 122
ZZ_NOUN _DET_ _VERB_ 59
zz_DET _NOUN_ . 86
ZZ is_VERB reached 42
ZZ_NUM ^ ^ 65
ZZ _NOUN_ _VERB_ 3163
ZZ ,_. " 52
ZZ / _NUM_ 275
Embora o exemplo represente uma matriz de 3 elementos, estou trabalhando com matrizes contendo de 1 a 5 elementos.
awk '{a[$1] +=$(NF-1)} END{for (i in a) print i, a[i]}'
awk '{a[$1" "$2] +=$(NF-1)} END{for (i in a) print i, a[i]}'
awk '{a[$1" "$2" "$3] +=$(NF-1)} END{for (i in a) print i, a[i]}'
awk '{a[$1" "$2" "$3" "$4] +=$(NF-1)} END{for (i in a) print i, a[i]}'
awk '{a[$1" "$2" "$3" "$3" "$5] +=$(NF-1)} END{for (i in a) print i, a[i]}'
Como posso dizer ao awk para comparar o array atual com o array anterior na linha anterior, em vez de fazer com que o awk tente combinar cada array com cada array em um arquivo ou pedaço?
Obrigado
Exemplo de arquivo fonte.
wget --show-progress -cq http://storage.googleapis.com/books/ngrams/books/googlebooks-eng-us-all-3gram-20120701-zz.gz -O - | zcat
Responder1
Os dados de entrada fornecidos como URL em um comentário são delimitados por tabulações. Isso significa que podemos analisar seu primeiro campo delimitado por tabulação como uma espécie de "chave" para comparar com outras linhas. Nós fazemosnãotem que se preocupar com as palavras separadas por espaço no primeiro campo, mas pode tratar todo o primeiro campo como uma entidade única.
BEGIN { OFS = FS = "\t" }
{
count = $(NF - 1)
key = $1
}
key != previous {
if (previous != "")
print previous, sum
sum = 0
}
{
sum += count
previous = key
}
END {
if (previous != "")
print previous, sum
}
Este awk
programa analisa o campo "contagem" (penúltimo campo) em e count
, em seguida, usa o primeiro campo como a "chave" para comparar posteriormente com a chave da linha anterior. Este é o primeiro bloco após o BEGIN
bloco (que apenas define os delimitadores de entrada e saída).
Se a tonalidade for diferente da tonalidade da linha anterior, isso significa que agora estamos olhando para algum outro conjunto de palavras. Produza a chave e a soma da linha anterior e redefina a soma.
Para todas as linhas, aumente a soma pela contagem desta linha e atualize previous
(agora terminamos esta linha, então esta linha key
é a próxima previous
).
No final, produza as informações da última linha dos dados.
Você executaria isso usando awk -f script.awk inputfile
.
Como uma "linha única":
awk -F '\t' 'BEGIN{OFS=FS} {c=$(NF-1);k=$1} k!=p {if(p!="")print p,s;s=0} {s+=c;p=k} END {if(p!="") print p,s}' file