[root@server]# awk '!seen[$0]++' out.txt > cleaned
awk: (FILENAME=out.txt FNR=8547098) fatal error: internal error
Aborted
[root@server]#
O "" servidor "" possui: 8 GByte RAM + 16 GByte SWAP, x> 300 GByte de espaço livre, amd64, CPU de desktop. Scientific Linux 6.6. Nada mais funciona para fazer LOAD. O awk é interrompido após alguns segundos .. out.txt é ~ 1,6 GByte. GNU Awk 3.1.7.
Pergunta : Como posso remover as linhas duplicadas, mantendo a ordem das linhas? Caso é importante também, por exemplo: "A" e "a" são duas linhas diferentes, tem que mantê-lo. Mas "a" e "a" são duplicados, apenas o primeiro é necessário.
A resposta pode estar em qualquer coisa .. se o awk não for bom para isso .. então perl / sed .. qual poderia ser o problema?
[root@server]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 61945
max locked memory (kbytes, -l) 99999999
max memory size (kbytes, -m) unlimited
open files (-n) 999999
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 99999999
cpu time (seconds, -t) unlimited
max user processes (-u) 61945
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
[root@server]#
Atualização: Eu tentei isso em uma máquina RHEL, ela não aborta, mas não tive tempo para esperar que ela terminasse. Por que o SL linux do SL difere do RHEL?
Atualização: Estou tentando um gues virtual do Ubuntu 14 .. até agora funciona! Não é um problema ulimit: mawk 1.3.3
root@asdf-VirtualBox:~# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 51331
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 51331
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
root@asdf-VirtualBox:~#
fonte
awk
versões em duas máquinas?out.txt
? O mesmo comando funciona se você tentar em um arquivo menor? Quantos usuários na máquina? Havia memória disponível suficiente para o processo? Existe algo de especial na linha 8547098 do arquivo de entrada?Respostas:
Duvido que faça alguma diferença, mas, apenas no caso, veja como fazer a mesma coisa no Perl:
Se o problema for manter as linhas exclusivas na memória, isso terá o mesmo problema que
awk
você tentou. Portanto, outra abordagem poderia ser:Como funciona:
Em um sistema GNU,
cat -n
o número da linha será anexado a cada linha, seguindo uma quantidade de espaços e seguido por um caractere <tab> .cat
canaliza essa representação de entrada parasort
.sort
A-k2
opção de instrui apenas a considerar os caracteres do segundo campo até o final da linha ao classificar esort
divide os campos por padrão no espaço em branco (oucat
nos espaços inseridos e <tab> ) .Quando seguido
-k1n
,sort
considera o segundo campo primeiro e, em seguida, em segundo lugar - no caso de-k2
campos idênticos - considera o 1º campo, mas classificado numericamente. Assim, as linhas repetidas serão classificadas juntas, mas na ordem em que apareceram.uniq
- que são instruídos a ignorar o primeiro campo (-f1
- e também separados por espaços em branco) - e resultam em uma lista de linhas exclusivas no arquivo original e são direcionados novamente parasort
.sort
classificado numericamente no primeiro campo (cat
número da linha inserido) , retornando a ordem de classificação ao que estava no arquivo original e canalizando esses resultadoscut
.cut
remove os números de linha que foram inseridos porcat
. Isso é feitocut
imprimindo apenas do 2º campo até o final da linha (ecut
o delimitador padrão é um caractere <tab> ) .Ilustrar:
fonte
sort
! Mas a maioriasort
pode fazeruniq
por si mesmo para que você possa curta você scriptsort -uk2 | sort -bk1,1n
sort
? Eu pensei que-u
era um recurso GNU.-u
e especificar que ele deve ignorar o 1º campo? De acordo comman sort
, essa-u
não é uma das opções possíveis-f
, então não acho que possa ser usada aqui.EDIT 1: Isso realmente funciona? (comparando)
Caso1 : 100_000_000 números aleatórios (5 dígitos cada), 566Mbytes, 31_212 valores diferentes:
Caso 2 : 50_000_000 números de rand (10 dígitos cada), 516Mbytes, 48_351_464 valores diferentes:
(os seguintes números não são muito precisos):
sol2 com cache é:
A classificação também pode ser otimizada, adicionando uma opção de tamanho do cache (não concluída).
Uma rápida conclusão:
sort
é um comando fantástico!fonte
sort -uk2
esort -nk1,1
são diferentes. O primeiro considera da tecla 2cd até o final da linha, o segundo considera apenas a primeira tecla. Você deve mudar o seusort -nk1
lá - pode até ser mais rápido assim, mas com certeza será mais confiável. A propósito - essas são algumas caixas bonitas.cat -n
acontece com uma guia ? Não sei como esse comando funciona.cat -n
transfrom cadaline
emspaces + the number + \t + line
- o formato ideal para classificar e corteEu usei
BINMODE = rw: para manter felizes os terminadores de fim de linha. (Eu moro em um ambiente misto)
A lógica é simples.
Se a linha atual não estiver na matriz associativa, adicione-a à matriz associativa e imprima na saída.
Pode haver limitações de memória com essa abordagem. Para arquivos e conjuntos de arquivos muito grandes, usei variações sobre isso, usando o armazenamento de arquivos para superar as limitações.
fonte
A semântica de preservação de ordem do seu problema tem uma propriedade maravilhosa: você pode subdividir o problema. Você pode fazer
split -l 1000000
no arquivo de entrada; as peças de 1000000 linhas produzidas têm nomes lexicamente ordenados, o que é bom; uniqify as peças; e então (como uma segunda passagem) uniqifique as saídas dessas.Isso resolve o problema de falta de memória (limitando o requisito de memória) às custas de transformá-lo em uma solução multipass.
Especificamente:
Gere dados de entrada:
Divida os dados de entrada:
Execute o uniqificador de uma só vez (mantém todas as linhas de entrada exclusivas na memória):
Execute o uniqificador em partes divididas (retém apenas linhas de entrada exclusivas de cada parte na memória) e reduza como uma segunda passagem:
Comparar:
Não conheço a proporção de linhas únicas para não exclusivas em sua entrada, nem quão bem misturadas são as linhas de entrada - portanto, há algumas opções a serem feitas em termos do número de arquivos divididos que você precisa.
fonte
Outra abordagem (que vale a pena postar como resposta separada) é: em vez da abordagem de arquivos divididos que cria arquivos temporários, faça os lotes no próprio software uniqifier. Por exemplo, usando uma implementação de uniqifier Ruby para fins explicativos:
A idéia é limpar o conjunto de hash de vez em quando. Então isso se torna iterativo:
Portanto, você pode executar esta versão limitada repetidamente, até que a contagem de linhas não mude de uma iteração para a seguinte.
Observe que essa técnica capped-uniqm é independente da linguagem: você pode limpar a
lines_seen
matriz a cada N linhas, esteja usando awk, python, perl, C ++, etc. Existem métodos de limpeza de conjunto para todas essas linguagens; Eu acreditoawk
'sdelete
é não-padrão, mas comum.fonte