Estoy tratando de ordenar en varias columnas. Los resultados no son los esperados.
Aquí están mis datos (personas.txt):
Simon Strange 62
Pete Brown 37
Mark Brown 46
Stefan Heinz 52
Tony Bedford 50
John Strange 51
Fred Bloggs 22
James Bedford 21
Emily Bedford 18
Ana Villamor 44
Alice Villamor 50
Francis Chepstow 56
Lo siguiente funciona correctamente:
bash-3.2$ sort -k2 -k3 <people.txt
Emily Bedford 18
James Bedford 21
Tony Bedford 50
Fred Bloggs 22
Pete Brown 37
Mark Brown 46
Francis Chepstow 56
Stefan Heinz 52
John Strange 51
Simon Strange 62
Ana Villamor 44
Alice Villamor 50
Pero lo siguiente no funciona como se esperaba:
bash-3.2$ sort -k2 -k1 <people.txt
Emily Bedford 18
James Bedford 21
Tony Bedford 50
Fred Bloggs 22
Pete Brown 37
Mark Brown 46
Francis Chepstow 56
Stefan Heinz 52
John Strange 51
Simon Strange 62
Ana Villamor 44
Alice Villamor 50
Estaba tratando de ordenar por apellido y luego por nombre, pero verán que los Villamor no están en el orden correcto. Tenía la esperanza de ordenar por apellido y luego, cuando los apellidos coincidieran, ordenar por nombre.
Parece que hay algo acerca de cómo debería funcionar esto que no entiendo. Por supuesto, podría hacerlo de otra manera (usando awk), pero quiero entender la ordenación.
Estoy usando el shell Bash estándar en Mac OS X.
Respuesta aceptada:
Una especificación clave como -k2
significa tener en cuenta todos los campos desde el 2 hasta el final de la línea. Entonces Villamor 44
termina antes de Villamor 50
. Dado que estos dos no son iguales, la primera comparación en sort -k2 -k1
es suficiente para discriminar estas dos líneas, y la segunda clave de clasificación -k1
no se invoca. Si los dos Villamor hubieran tenido la misma edad, -k1
habría causado que se clasificaran por nombre.
Para ordenar por una sola columna, use -k2,2
como especificación clave. Esto significa usar los campos del #2 al #2, es decir, solo el segundo campo.
sort -k2 -k3 <people.txt
es redundante:es equivalente a sort -k2 <people.txt
. Para ordenar por apellidos, luego nombres y luego edad, ejecute el siguiente comando:
sort -k2,2 -k1,1 <people.txt
o equivalentemente sort -k2,2 -k1 <people.txt
ya que solo existen estos tres campos y los separadores son los mismos. De hecho, obtendrá el mismo efecto de sort -k2,2 <people.txt
, porque sort
usa toda la línea como último recurso cuando todas las claves en un subconjunto de líneas son idénticas.
También tenga en cuenta que el separador de campo predeterminado es la transición entre un espacio en blanco y otro que no está en blanco, por lo que las claves incluirán los espacios en blanco iniciales (en su ejemplo, para la primera línea, la primera clave será "Emily"
, pero la segunda clave " Bedford"
. Agregue el -b
opción para eliminar esos espacios en blanco:
sort -b -k2,2 -k1,1
También se puede hacer por tecla agregando b
indicador al final de la especificación de inicio clave:
sort -k2b,2 -k1,1 <people.txt
Pero algo a tener en cuenta:tan pronto como agregue una de esas banderas a la especificación clave, las banderas globales (como -n
, -r
…) ya no se aplican a ellos, por lo que es mejor evitar mezclar banderas por tecla y banderas globales.