2009-09-21 7 views
2

Je dispose d'un fichier texte comme celui-ci:Comment écrire un script shell qui filtre les lignes et les compte?

Apple 
Orange 
Orange 
Banana 
Banana 
Orange 
Banana 
Orange 
Apple 
Orange 

Je veux produire la sortie suivante après l'exécution d'un script shell bash:

Apple: 2 
Orange: 5 
Banana: 3 

Il est plutôt standard si j'utilise un langage complet soufflé comme Java/C++ etc. mais quel est le moyen le plus rapide de le faire avec un script shell/une ligne de commande?

+0

devoirs, hein? –

+0

@Dennis: Ou combiner une tonne de fiction internet (avec des informations de localisation d'auteur) avec une liste de fruits pour faire une étude sur la prévalence des fruits par rapport à la région! N'êtes-vous pas curieux? – Cascabel

Répondre

13
sort $FILE | uniq -c 

vous donnera

2 Apple 
3 Banana 
5 Orange 
+1

et pour reformater, vous pouvez utiliser perl comme NawaMan dit, ou sed: '... | sed -r 's/* ([0-9]) + * (. *)/\ 2: \ 1 /' '(le' -r' le change en regex étendu, et la substitution est la même que celle de NawaMan sans les supports inutiles). – Cascabel

+0

est d'accord avec cela comme meilleur, parce que c'est comme si l'utilisateur est flexible sur le format de sortie. Les exigences sont souvent acceptées après le démarrage d'une boîte de dialogue. – ericslaw

4

nom de fichier de tri | uniq -c | awk '{print $ 2 ":" $ 1}'

+0

Pas besoin de chat! – Cascabel

+0

convenu, pas besoin de chat – rangalo

+0

L'awk supplémentaire le formater comme requis – rangalo

2
uniq -c $FILE | perl -pe 's|[ ]*([0-9]+)[ ]*(.*)|\2: \1|'

Cela forme à la façon de spécifiée. Vous pouvez ajouter '| sorte 'à la fin le genre aussi.

EDIT: Comme le souligne le commentaire, je fais une erreur à propos de uniq donc voici le corrigé.

sort $FILE | uniq -c | perl -pe 's|[ ]*([0-9]+)[ ]*(.*)|\2: \1|'

Désolé pour le problème.

+0

'uniq' vérifie les lignes identiques consécutives. Vous devez trier la liste en premier. – Cascabel

+0

Merci d'avoir signalé cela. J'avais surtout l'habitude de déjà trier les données, donc j'ai oublié ça. – NawaMan

4

Cette solution utilise un seul outil: awk

$ awk '{count[$0]++} END {for (c in count) {print c ": " count[c]}} ' count.txt 
Orange: 5 
Banana: 3 
Apple: 2 
Questions connexes