Ordenar líneas por número de palabras por línea

14

Entrada dada:

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

Me gustaría ordenarlo en la mayoría de las palabras en la parte superior, al menos al final, así:

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

¿Cómo haría esto con sortalguna otra herramienta?

Caleb Xu
fuente
Para ser claros, desea ordenar por número de palabras, no ordenar por longitud de línea (con su entrada de muestra, la línea con más palabras también es la más larga, pero ese no siempre es el caso).
don_crissti
Si. La línea con más palabras no es necesariamente la más larga en general. Por ejemplo, quiero bin: bop boopantes boatkeeper: poughkeepsie. Si dos líneas comparten el mismo número de palabras, preferiría que los lazos se alfabetizaran, pero eso no es un requisito.
Caleb Xu

Respuestas:

22

Podrías hacer algo como:

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

Usamos awkpara prefijar el número de campos a cada línea. Luego, sortpor ese número y lo eliminamos con cut.

Corazón oscuro
fuente
Esto funcionó. Me preguntaba por qué se invirtió el orden, pero ahora veo su edición.
Caleb Xu
6

En GNU reciente, awkse puede usar la PROCINFOmatriz para definir muchos parámetros internos, incluido el orden en que se imprimen los elementos de la matriz (controlados por elemento "sorted_in"). Por lo tanto, podemos construir e indexar con el valor de NF" "NR, qué elementos tienen valor $0e imprimirlo en la salida deseada, en su caso, sería "@ind_num_desc":

awk '{a[NF" "NR]=$0}END{PROCINFO["sorted_in"]="@ind_num_desc"; for(i in a) print a[i]}' file
jimmij
fuente
1
+1 pensaba lo mismo: sin embargo, uno debería tener en cuenta que tendrá el efecto secundario de desduplicar la entrada
steeldriver
@steeldriver tienes toda la razón, edité mi respuesta, debería estar bien ahora.
jimmij
Esto ahora conserva el orden original entre registros con el mismo número de campos, en lugar de ordenar las palabras como una clave de clasificación secundaria. Si sus claves fueran NF" "$0" "NR, solo tendría NRun mecanismo de respaldo / manejo de duplicados.
Peter Cordes
1
@PeterCordes pero eso revertiría el orden de las palabras, no veo forma de resolver los lazos alfabéticamente, aparte de que, por definición, la propia función cmp_func(), gnu awk lo permite.
jimmij
5

Perl one-liner:

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

Si quieres romper los lazos usando el orden alfabético:

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

A través de pitón.

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)

o

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
fuente