Sortuj wiersze według liczby słów w wierszu

14

Biorąc pod uwagę wkład:

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

Chciałbym posortować to na większość słów na górze, przynajmniej na końcu, tak:

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

Jak mam to zrobić za pomocą sortinnego narzędzia?

Caleb Xu
źródło
Żeby było jasne, chcesz sortować według liczby słów, a nie według długości linii (przy wprowadzaniu próbki linia z największą liczbą słów jest również najdłuższa, ale nie zawsze tak jest)?
don_crissti
Tak. Linia z największą liczbą słów niekoniecznie musi być najdłuższa. np. chcę bin: bop boopwcześniej boatkeeper: poughkeepsie. Jeśli dwa wiersze dzielą tę samą liczbę słów, wolałbym, aby krawaty były alfabetycznie, ale nie jest to wymagane.
Caleb Xu,

Odpowiedzi:

22

Możesz zrobić coś takiego:

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

Używamy awkdo prefiksu liczby pól w każdej linii. Następnie sortpod tym numerem i usuwamy go za pomocą cut.

Ciemne serce
źródło
To zadziałało. Zastanawiałem się, dlaczego kolejność została odwrócona, ale teraz widzę twoją zmianę.
Caleb Xu,
6

W najnowszym GNU awkmożna użyć PROCINFOtablicy do zdefiniowania wielu parametrów wewnętrznych, w tym kolejności drukowania elementów tablicy (kontrolowanych przez element "sorted_in"). W ten sposób możemy zbudować i zindeksować tablicę z wartością NF" "NR, które elementy mają wartość, $0i wydrukować ją w pożądanym wyniku, w twoim przypadku byłoby to "@ind_num_desc":

awk '{a[NF" "NR]=$0}END{PROCINFO["sorted_in"]="@ind_num_desc"; for(i in a) print a[i]}' file
jimmij
źródło
1
+1 myślał o tym samym: należy jednak pamiętać, że będzie to miało efekt uboczny polegający na usunięciu duplikacji danych wejściowych
steeldriver
@steeldriver masz całkowitą rację, zredagowałem moją odpowiedź, teraz powinno być dobrze.
jimmij
To teraz zachowuje oryginalne uporządkowanie między rekordami o tej samej liczbie pól, zamiast sortowania według słów jako dodatkowego klucza sortowania. Gdybyś miał klucze NF" "$0" "NR, miałbyś tylko NRmechanizm rezerwowy / obsługi duplikatów.
Peter Cordes
1
@PeterCordes, ale to odwróciłoby kolejność słów, nie widzę innego sposobu na alfabetyczne rozwiązywanie więzi niż te z definicji własnej funkcji cmp_func()- gnu awk na to pozwala.
jimmij
5

Perl One-Liner:

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

Jeśli chcesz zerwać więzi w kolejności alfabetycznej:

print sort { split(' ',$a) <=> split(' ',$b) or $a cmp $b } <>;
Nate Eldredge
źródło
4

Poprzez 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)

lub

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="")
Avinash Raj
źródło