J'ai 100 millions de lignes dans mon fichier.
Chaque ligne n'a qu'une seule colonne.
par exemple
aaaaa
bb
cc
ddddddd
ee
Je voudrais lister le nombre de caractères
Comme ça
2 character words - 3
5 character words - 1
7 character words - 1
etc.
Existe-t-il un moyen simple de le faire dans le terminal?
text-processing
Giri
la source
la source
Réponses:
Le premier
awk
filtre affichera simplement la longueur de chaque ligne du fichier appeléfile
. Je suppose que ce fichier contient un mot par ligne.Le
sort -n
(trier les lignes de la sortie deawk
numériquement dans l'ordre croissant) etuniq -c
(compter le nombre de fois où chaque ligne se produit consécutivement) créera alors la sortie suivante à partir de celle pour les données données:Ceci est ensuite analysé par le deuxième
awk
script qui interprète chaque ligne comme "X nombre de lignes ayant Y caractères" et produit la sortie souhaitée.La solution alternative consiste à tout faire
awk
et à conserver le nombre de longueurs dans un tableau. C'est un compromis entre efficacité, lisibilité / facilité de compréhension (et donc maintenabilité) quelle solution est la "meilleure".Solution alternative:
la source
Une autre façon de tout faire
awk
seulwords[length()]++
utiliser la longueur de la ligne d'entrée comme clé pour enregistrer le nombreEND{for(k in words)print k " character words - " words[k]}
une fois toutes les lignes traitées, imprimer le contenu du tableau au format souhaitéComparaison des performances, les nombres sélectionnés sont les meilleurs des deux essais
Si le fichier ne contient que des caractères ASCII,
Je ne sais pas pourquoi le temps
perl
n'a pas beaucoup changé, probablement l'encodage doit être réglé d'une autre manièrela source
length
sans()
travaux parfaitement bien ici, il pourrait donc être redondant d'ajouter des accolades. J'utilise GNU awk, cependant.In older versions of awk, the length() function could be called without any parentheses. Doing so is considered poor practice, although the 2008 POSIX standard explicitly allows it, to support historical practice. For programs to be maximally portable, always supply the parentheses
Voici un
perl
équivalent (avec - optionnel - sort):la source
{$a<=>$b}
après lesort
permettrait de résoudre ce problème. Alternativement, on pourrait utiliser un tableau normal avec des touches numériques et simplement sauter toutes les clés dont la valeur est zéro / non définie.Une alternative un appel à GNU awk, en utilisant printf :
L'algorithme de base collecte simplement le nombre de caractères dans un tableau. La partie finale imprime les comptes collectés formatés avec printf.
Rapide, simple, un seul appel à awk.
Pour être précis: un peu plus de mémoire est utilisée pour conserver le tableau.
Mais aucun tri n'est appelé (les index des tableaux numériques sont définis pour être toujours parcourus triés vers le haut avec PROCINFO), et un seul programme externe:,
awk
au lieu de plusieurs.la source
for in
peut arriver à donner des index de tableau numérique dans l'ordre numérique au moins pour certaines valeurs ou dans certaines implémentations awk, mais ce n'est pas obligatoire, pas traditionnel et certainement pas universel. Cela arrive souvent pour de petits ensembles comme 2 ou 3 ou peut-être 4; essayez 10 ou 20 sur chaque awk auquel vous avez accès (sans PROCINFO ou WHINY_USERS dans gawk) et je parie que 50 $ au moins un cas n'est pas trié.@ind_str_asc
trie sous forme de chaînes, ce qui ne sera correct pour les nombres que s'ils sont tous à un seul chiffre (comme dans votre exemple); utilisez@ind_num_asc
si (n'importe laquelle) les valeurs peuvent être 10 ou plus. Et bien que ce soit moins un problème maintenant qu'auparavant, cette fonctionnalité n'est que gawk 4.0 .