[root@server]# awk '!seen[$0]++' out.txt > cleaned
awk: (FILENAME=out.txt FNR=8547098) fatal error: internal error
Aborted
[root@server]#
Le "" serveur "" a: 8 Go de RAM + 16 Go de SWAP, x> 300 Go d'espace libre, amd64, CPU de bureau. Scientific Linux 6.6. Rien d'autre ne tourne dessus pour faire de la CHARGE. Awk s'interrompt après quelques secondes. Out.txt fait ~ 1,6 Go. GNU Awk 3.1.7.
Question : Comment puis-je supprimer les lignes en double tout en conservant l'ordre des lignes? La casse est aussi importante, ex: "A" et "a" sont deux lignes différentes, faut la garder. Mais "a" et "a" est en double, seul le premier est nécessaire.
La réponse pourrait être dans n'importe quoi .. si awk n'est pas bon pour cela .. alors perl / sed .. quel pourrait être le problème?
[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]#
Mise à jour: J'ai essayé cela sur une machine RHEL, cela n'interrompt pas, mais je n'ai pas eu le temps d'attendre qu'elle se termine. Pourquoi SL SL Linux ne diffère-t-il pas de RHEL?
Mise à jour: J'essaie un gues virtuel Ubuntu 14 .. jusqu'à présent ça marche! Ce n'est pas un problème ultime : 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:~#
la source
awk
versions sur deux machines?out.txt
? La même commande fonctionne-t-elle si vous l'essayez sur un fichier plus petit? Combien d'utilisateurs sur la machine? Y avait-il suffisamment de mémoire disponible pour le processus? Y a-t-il quelque chose de spécial à propos de la ligne 8547098 du fichier d'entrée?Réponses:
Je doute que cela fasse une différence, mais au cas où, voici comment faire la même chose en Perl:
Si le problème est de conserver les lignes uniques en mémoire, cela aura le même problème que celui que
awk
vous avez essayé. Ainsi, une autre approche pourrait être:Comment ça fonctionne:
Sur un système GNU,
cat -n
ajoutera le numéro de ligne à chaque ligne en suivant une certaine quantité d'espaces et suivi d'un caractère <tab> .cat
redirige cette représentation d'entrée verssort
.sort
L'-k2
option lui indique de ne considérer que les caractères du deuxième champ jusqu'à la fin de la ligne lors du tri, etsort
divise les champs par défaut sur les espaces blancs (oucat
les espaces insérés et <tab> ) .Lorsqu'il est suivi de
-k1n
,sort
considère le premier champ en premier, puis deuxièmement - dans le cas de-k2
champs identiques - il considère le 1er champ mais comme trié numériquement. Les lignes répétées seront donc triées ensemble mais dans l'ordre où elles sont apparues.uniq
- auquel il est dit d'ignorer le premier champ (-f1
- et également séparés par des espaces) - et qui se traduit par une liste de lignes uniques dans le fichier d'origine et est redirigé verssort
.sort
trie numériquement le premier champ (cat
le numéro de ligne inséré) , ramenant l'ordre de tri à ce qu'il était dans le fichier d'origine et redirige ces résultatscut
.cut
supprime les numéros de ligne insérés parcat
. Ceci est effectué encut
imprimant uniquement à partir du 2ème champ jusqu'à la fin de la ligne (etcut
le délimiteur par défaut est un caractère <tab> ) .Pour illustrer:
la source
sort
! Mais la plupartsort
peuvent le faireuniq
par eux-mêmes afin que vous puissiez raccourcir votre script parsort -uk2 | sort -bk1,1n
sort
? Je pensais que-u
c'était une fonctionnalité GNU.-u
et spécifier qu'il doit ignorer le 1er champ? Selonman sort
, le-u
n'est pas l'une des options possibles-f
, donc je ne pense pas qu'il puisse être utilisé ici.EDIT 1: ça marche vraiment? (comparant)
Cas 1 : 100_000_000 nombres aléatoires (5 chiffres chacun), 566 Mo, 31_212 valeurs différentes:
Cas 2 : 50_000_000 rands (10 chiffres chacun), 516 Mo, 48_351_464 valeurs différentes:
(les chiffres suivants ne sont pas très précis):
sol2 avec cache est:
Le tri peut également être optimisé en ajoutant une option de taille de cache (non effectuée).
Une conclusion rapide:
sort
est une commande fantastique!la source
sort -uk2
etsort -nk1,1
sont différents. Le premier considère de la clé 2cd jusqu'à la fin de la ligne, le second ne considère que la première clé. Vous devriez y changersort -nk1
- cela pourrait même être plus rapide de cette façon, mais ce sera certainement plus fiable. Au fait, ce sont de jolies boîtes.cat -n
fait un onglet ? Je ne sais pas comment fonctionne cette commande.cat -n
transfrom chacunline
dansspaces + the number + \t + line
- le format idéal pour le tri et la coupeJ'ai utilisé
BINMODE = rw: pour satisfaire les terminateurs de fin de ligne. (Je vis dans un environnement de système d'exploitation mixte)
La logique est simple.
Si la ligne actuelle n'est pas dans le tableau associatif, ajoutez-la au tableau associatif et imprimez-la en sortie.
Il peut y avoir des limitations de mémoire avec cette approche. Pour les fichiers et les ensembles de fichiers très volumineux, j'ai utilisé des variantes à ce sujet, en utilisant le stockage de fichiers pour dépasser les limites.
la source
La sémantique préservant l'ordre de votre problème a une merveilleuse propriété: vous pouvez subdiviser le problème. Vous pouvez le faire
split -l 1000000
sur le fichier d'entrée; les pièces de 1000000 lignes qu'il produit ont des noms lexicaux, ce qui est bien; puis uniqifiez les pièces; puis (comme deuxième passage) unifier les sorties de ceux-ci.Cela résout le problème de mémoire insuffisante (en plafonnant les besoins en mémoire) au détriment de le transformer en une solution multipass.
Plus précisément:
Générez des données d'entrée:
Répartissez les données d'entrée:
Exécutez uniqifier en une seule fois (conserve toutes les lignes d'entrée uniques en mémoire):
Exécutez l'uniqifier sur les pièces séparées (ne conserve que les lignes d'entrée uniques de chaque pièce en mémoire), puis réduisez-les en deuxième passage:
Comparer:
Je ne connais pas le rapport entre les lignes uniques et non uniques dans votre entrée, ni la façon dont les lignes d'entrée sont bien mélangées - il y a donc un réglage à faire en termes de nombre de fichiers divisés dont vous avez besoin.
la source
Une autre approche (qui vaut la peine d'être publiée comme réponse distincte) est la suivante: au lieu de l'approche du fichier fractionné qui crée des fichiers temporaires, faites le traitement par lots dans le logiciel uniqifier lui-même. Par exemple, en utilisant une implémentation Ruby uniqifier à des fins explicatives:
L'idée est d'effacer le jeu de hachage de temps en temps. Cela devient alors itératif:
Vous pouvez donc exécuter cette version plafonnée à plusieurs reprises, jusqu'à ce que le nombre de lignes ne change pas d'une itération à la suivante.
Notez que cette technique capped-uniqm est indépendante du langage: vous pouvez effacer le
lines_seen
tableau toutes les N lignes, que vous utilisiez awk, python, perl, C ++, etc. Il existe des méthodes set-clear pour tous ces langages; Je crois que celuiawk
-cidelete
est non standard mais commun.la source