web-dev-qa-db-fra.com

Sortie de colonne inversée avec commande de tri

Je dois trier tous les mots d'un fichier donné en paramètre dans un script Shell. Voici le one-liner:

tr  [:space:] '\n' <$1  | sort -nrk2,2 | uniq -c |sed 's/^ \+//g'

En gros, si j'ai quelque chose comme ça dans mon dossier:

bla bla bla bla hu hu hu

Il va sortir

4 bla
3 hu

Je veux qu'ils soient quelque chose comme

bla 4
hu 3
2
gigiman

Vous pouvez remplacer votre commande sed par une simple commande awk qui permute l'ordre des champs.

... | awk '{print $2,$1}'
4
steeldriver

Il y a beaucoup de façons de faire cela. Steeldriver vous a déjà présenté l'approche classique awk. Voici quelques autres choix:

  1. Utilisez sed pour capturer deux groupes de caractères autres qu’espaces (\S), puis alternez-les:

    ... | sed -E 's/\s*(\S+)\s+(\S+)/\2 \1/'
    
  2. Utilisez Perl. Son commutateur -a le fait fonctionner comme awk. Il scinde automatiquement chaque ligne d'entrée en blanc et enregistre chaque champ en tant qu'élément du tableau @F. Par conséquent, le premier champ sera $F[0], le second $F[1] etc .:

    ... | Perl -lane 'print "$F[1] $F[0]"'
    
  3. Utilisez Perl pour le tout:

    Perl -lane '$k{$_}++ for @F; }{ print "$_ $k{$_}" for keys(%k)' "$1"
    

    Ici, Perl lit le fichier d'entrée ligne par ligne et applique le script à chaque ligne. $k{$_}++ for @F enregistre chaque mot (chaque champ de @F) en tant que clé dans le hachage %k et incrémente la valeur associée d'un à chaque fois que le mot est vu. Ensuite, une fois que le fichier a été traité (c'est ce que signifie }{), il imprimera le mot ($_) et le nombre de fois qu'il a été vu ($k{$_}) pour chaque clé. stocké dans le hachage.

  4. Utilisez awk pour le tout:

    awk '{for(i=1;i<=NF;i++){a[$i]++}}END{for(i in a){print i,a[i]}}' "$1"
    

    La première boucle for survole chaque champ et en ajoute un à la valeur associée à ce champ dans le tableau a. Puis, à la fin du fichier, il boucle sur chaque élément de a et affiche l'élément (le mot) et la valeur associée (le nombre de fois que le mot a été vu).

  5. Utilisez le shell avec votre pipeline d'origine:

    ... | while read a b; do echo "$b $a"; done
    
6
terdon