J'ai un fichier texte avec 2 millions de lignes. Chaque ligne a un entier positif. J'essaie de former une sorte de tableau de fréquences.
Fichier d'entrée:
3
4
5
8
La sortie doit être:
3
7
12
20
Comment dois-je procéder?
command-line
text-processing
Monty Harder
la source
la source
Réponses:
Avec
awk
:$0
est la ligne actuelle. Donc, pour chaque ligne, je l'ajoute à latotal
, définit la ligne sur la nouvelletotal
, puis la fin1
est un raccourci awk - il imprime la ligne actuelle pour chaque condition vraie, et1
comme une condition est évaluée comme vraie.la source
print
peut-il également être utilisé?print total}
au lieu de$0 = total}1
{print(total += $0)}
Dans un script python:
Utiliser
add_last.py
Exécutez-le avec le fichier source et le fichier de sortie ciblé comme arguments:
Explication
Le code est plutôt lisible, mais en détail:
Ouvrir le fichier de sortie pour écrire les résultats
Ouvrir le fichier d'entrée pour la lecture par ligne
Lisez les lignes, en ajoutant la valeur de la nouvelle ligne au total:
Écrivez le résultat dans le fichier de sortie:
la source
Juste pour le fun
Cela fonctionne par un ppending
+p
à chaque ligne de l'entrée, et en faisant passer le résultat à ladc
calculatrice oùpuis
L'
-e0
argument pousse0
sur ladc
pile pour initialiser la somme.la source
real 0m4.234s
Dans Bash:
la source
real 0m53.116s
près d'une minute, sur 1,3 million de lignes :)Pour imprimer une somme partielle d'entiers donnée sur l'entrée standard, une par ligne:
Exemple exécutable .
Si pour une raison quelconque, la commande est trop lente; vous pouvez utiliser le programme C:
Pour le construire et l'exécuter, tapez:
Exemple exécutable .
UINTMAX_MAX
est18446744073709551615
.Le code C est plusieurs fois plus rapide que la commande awk sur ma machine pour le fichier d'entrée généré par:
la source
accumulate()
itertoolVous voulez probablement quelque chose comme ça:
Explication de la commande:
sort -n <filename> | uniq -c
trie l'entrée et renvoie une table de fréquences| awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}'
transforme la sortie en un format plus agréableExemple:
fichier d'entrée
list.txt
:La commande:
la source
Vous pouvez le faire dans vim. Ouvrez le fichier et saisissez les touches suivantes:
Notez que
<C-a>
c'est en fait ctrl-a, et<cr>
est un retour chariot , c'est-à-dire le bouton Entrée.Voici comment cela fonctionne. Tout d'abord, nous voulons effacer le registre «a» afin qu'il n'ait aucun effet secondaire la première fois. C'est tout simplement
qaq
. Ensuite, nous faisons ce qui suit:Une fois cette macro récursive exécutée, nous appelons simplement
:wq<cr>
à enregistrer et à quitter.la source
Perl one-liner:
Avec 2,5 millions de lignes de chiffres, il faut environ 6,6 secondes pour traiter:
la source
real 0m0.908s
, plutôt sympa.Une simple doublure Bash:
x
est la somme cumulée de tous les nombres de la ligne actuelle et au-dessus.n
est le numéro de la ligne actuelle.Nous bouclons sur toutes les lignes
n
deINPUT_FILE
et ajoutons leur valeur numérique à notre variablex
et imprimons cette somme à chaque itération.Bash est un peu lent ici cependant, vous pouvez vous attendre à ce que cela dure environ 20-30 secondes pour un fichier avec 2 millions d'entrées, sans imprimer la sortie sur la console (ce qui est encore plus lent, indépendamment de la méthode que vous utilisez).
la source
Semblable à la réponse de @ steeldriver, mais avec un peu moins d'arcane à la
bc
place:La bonne chose à propos de
bc
(etdc
) est qu'ils sont des calculateurs de précision arbitraires, donc ils ne déborderont jamais ou ne souffriront pas d'un manque de précision sur les entiers.L'
sed
expression transforme l'entrée en:Ceci est ensuite évalué par
bc
. Laa
variable bc est initialisée automatiquement à 0. Chaque ligne s'incrémentea
, puis l'imprime explicitement.la source
real 0m5.642s
sur 1,3 million de lignes. sed est vraiment lent à ce sujet.