Trier les lignes par nombre de mots par ligne


14

Contribution donnée:

hello: world foo bar baz
bar:
baz: bin boop bop fiz bang beep
bap: bim bam bop
boatkeeper: poughkeepsie

Je voudrais le trier dans la plupart des mots en haut, au moins à la fin, comme ceci:

baz: bin boop bop fiz bang beep
hello: world foo bar baz
bap: bim bam bop
boatkeeper: poughkeepsie
bar:

Comment pourrais-je faire cela avec sortun autre outil?


Juste pour être clair, vous voulez trier par nombre de mots et non par longueur de ligne (avec votre entrée d'échantillon, la ligne avec le plus de mots est également la plus longue mais ce n'est pas toujours le cas)?
don_crissti

Oui. La ligne avec le plus de mots n'est pas nécessairement la plus longue en général. par exemple, je veux bin: bop boopavant boatkeeper: poughkeepsie. Si deux lignes partagent le même nombre de mots, je préférerais que les liens soient alphabétisés, mais ce n'est pas une exigence.
Caleb Xu

Réponses:


22

Vous pourriez faire quelque chose comme:

awk '{print NF,$0}' file | sort -nr | cut -d' ' -f 2-

Nous utilisons awkpour préfixer le nombre de champs à chaque ligne. Nous avons ensuite sortpar ce numéro et le retirer avec cut.


Cela a fonctionné. Je me demandais pourquoi l'ordre a été inversé, mais je vois votre modification maintenant.
Caleb Xu

6

Dans GNU récent, awkon peut utiliser un PROCINFOtableau pour définir de nombreux paramètres internes, y compris l'ordre dans lequel les éléments du tableau sont imprimés (contrôlés par élément "sorted_in"). Ainsi, nous pouvons construire et tableau indexé avec la valeur de NF" "NR, quels éléments ont une valeur de $0et l'imprimer dans la sortie souhaitée, dans votre cas, ce serait "@ind_num_desc":

awk '{a[NF" "NR]=$0}END{PROCINFO["sorted_in"]="@ind_num_desc"; for(i in a) print a[i]}' file

1
+1 pensait la même chose: cependant, il faut peut-être noter que cela aura pour effet secondaire de
dédupliquer

@steeldriver vous avez absolument raison, j'ai édité ma réponse, ça devrait aller maintenant.
jimmij

Cela préserve désormais l'ordre d'origine entre les enregistrements avec le même nombre de champs, au lieu de trier les mots comme une clé de tri secondaire. Si vos clés l'étaient NF" "$0" "NR, vous n'auriez qu'un NRmécanisme de secours / de gestion des doublons.
Peter Cordes

1
@PeterCordes mais cela inverserait l'ordre des mots, je ne vois aucun moyen de résoudre les liens par ordre alphabétique autre que par définition propre fonction cmp_func()- gnu awk le permet.
jimmij

5

Perl one-liner:

print sort { split(' ',$a) <=> split(' ',$b) } <>;

Si vous souhaitez rompre les liens en utilisant l'ordre alphabétique:

print sort { split(' ',$a) <=> split(' ',$b) or $a cmp $b } <>;

4

Par python.

s = '''hello: world foo bar baz
bar:
baz: bin boop bop fiz bang beep
bap: bim bam bop'''.splitlines()
for i in sorted(s, key=lambda x: len(x.split()), reverse=True):
    print(i)

ou

with open('/path/to/the/input/file') as f:
    m = f.readlines()
    for i in sorted(m, key=lambda x: len(x.split()), reverse=True):
        print(i, end="")
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.