Classifique as linhas pelo número de palavras por linha

14

Dados fornecidos:

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

Gostaria de classificá-lo na maioria das palavras no topo, no mínimo no final, da seguinte forma:

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

Como eu faria isso com sortou com alguma outra ferramenta?

Caleb Xu
fonte
Só para esclarecer, você deseja classificar por número de palavras e não por comprimento de linha (com sua amostra inserida, a linha com mais palavras também é a mais longa, mas que nem sempre pode ser o caso)?
don_crissti
Sim. A linha com mais palavras não é necessariamente a mais longa em geral. por exemplo, eu quero bin: bop boopantes boatkeeper: poughkeepsie. Se duas linhas compartilham o mesmo número de palavras, eu preferiria que os laços fossem alfabetizados, mas isso não é um requisito.
Caleb Xu

Respostas:

22

Você poderia fazer algo como:

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

Usamos o awkprefixo do número de campos para cada linha. Então, sortpor esse número e removê-lo com cut.

DarkHeart
fonte
Isso funcionou. Estava me perguntando por que o pedido foi revertido, mas agora vejo sua edição.
Caleb Xu
6

No GNU recente, awké possível usar o PROCINFOarray para definir muitos parâmetros internos, incluindo a ordem na qual os elementos do array são impressos (controlados pelo elemento "sorted_in"). Assim, podemos construir e matriz indexados com o valor de NF" "NR, quais elementos têm valor $0e imprimi-lo na saída desejada, no seu caso, seria "@ind_num_desc":

awk '{a[NF" "NR]=$0}END{PROCINFO["sorted_in"]="@ind_num_desc"; for(i in a) print a[i]}' file
jimmij
fonte
1
+1 estava pensando a mesma coisa: no entanto deve-se talvez notar que ele vai ter o efeito colateral de de-duplicação de entrada
steeldriver
@steeldriver você está absolutamente correto, eu editei minha resposta, deve ficar bem agora.
jimmij
Agora, isso preserva a ordem original entre registros com o mesmo número de campos, em vez de classificar as palavras como uma chave de classificação secundária. Se suas chaves fossem NF" "$0" "NR, você teria apenas NRum mecanismo de manipulação de fallback / duplicado.
22615 Peter Cordes
1
@ PeterCordes, mas isso reverteria a ordem das palavras, não vejo como resolver vínculos em ordem alfabética, exceto por definição própria função cmp_func()- o gnu awk permite isso.
jimmij
5

One-liner Perl:

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

Se você deseja quebrar os laços usando ordem alfabética:

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

Através de 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="")
Avinash Raj
fonte