Сортировка строк по количеству слов в строке

14

Учитывая вход:

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

Я хотел бы отсортировать его по большинству слов вверху, по крайней мере в конце, например:

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

Как бы я сделал это с sortили другим инструментом?

Калеб Сюй
источник
Просто чтобы прояснить, вы хотите отсортировать по количеству слов, а не по длине строки (в вашем примере ввода строка с наибольшим количеством слов также самая длинная, но это не всегда так)?
don_crissti
Да. Строка с большинством слов не обязательно самая длинная в целом. например, я хочу bin: bop boopраньше boatkeeper: poughkeepsie. Если две строки имеют одинаковое количество слов, я бы предпочел, чтобы связи были в алфавитном порядке, но это не является обязательным требованием.
Калеб Сюй

Ответы:

22

Вы могли бы сделать что-то вроде:

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

Мы используем awkдля префикса количество полей в каждой строке. Затем мы sortпо этому номеру и удалить его с cut.

Темное сердце
источник
Это сработало. Было интересно, почему заказ был отменен, но я вижу ваше изменение сейчас.
Калеб Сюй
6

В недавнем GNU awkможно использовать PROCINFOмассив для определения многих внутренних параметров, включая порядок, в котором печатаются элементы массива (управляется элементом "sorted_in"). Таким образом, мы можем построить и проиндексировать массив со значением NF" "NR, для которого элементы имеют значение, $0и вывести его в желаемом выводе, в вашем случае это будет "@ind_num_desc":

awk '{a[NF" "NR]=$0}END{PROCINFO["sorted_in"]="@ind_num_desc"; for(i in a) print a[i]}' file
jimmij
источник
1
+1 думал о том же: однако, возможно, следует заметить, что побочным эффектом дедупликации будет побочный эффект
steeldriver
@steeldriver Вы абсолютно правы, я отредактировал свой ответ, теперь все должно быть в порядке.
Джимми
Это теперь сохраняет исходный порядок между записями с одинаковым количеством полей вместо сортировки по словам в качестве вторичного ключа сортировки. Если бы ваши ключи были NF" "$0" "NR, у вас был бы только NRмеханизм резервирования / обработки дубликатов.
Питер Кордес
1
@PeterCordes, но это изменило бы порядок слов, я не вижу способа разрешить связи в алфавитном порядке, кроме как по определению собственной функции cmp_func()- gnu awk позволяет это.
jimmij
5

Perl однострочный:

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

Если вы хотите разорвать связи в алфавитном порядке:

print sort { split(' ',$a) <=> split(' ',$b) or $a cmp $b } <>;
Нейт Элдридж
источник
4

Через питона.

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)

или

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="")
Авинаш Радж
источник