Ordenar múltiples claves con ordenación Unix

137

Tengo archivos potencialmente grandes que necesitan ser ordenados por claves 1-n. Algunas de estas teclas pueden ser numéricas y algunas de ellas pueden no serlo. Este es un archivo columnar de ancho fijo, por lo que no hay delimitadores.

¿Hay una buena manera de hacer esto con Unix sort? Con una tecla es tan simple como usar '-n'. Leí la página del manual y busqué en Google brevemente, pero no encontré un buen ejemplo. ¿Cómo haría para lograr esto?

Nota: He descartado Perl debido al potencial de tamaño del archivo. Sería un último recurso.

Chris Kloberdanz
fuente
Una o dos líneas de datos de ejemplo serían realmente útiles para crear una línea de comando de ejemplo. Además, ¿las teclas "1-n" significan que necesita ordenar por un número variable de teclas? Hacer eso sin secuencias de comandos será divertido ...
Ken Gentle
Tengo un contenedor PHP alrededor del comando de clasificación para habilitar la función 1-n.
Chris Kloberdanz

Respuestas:

69

Use la -kopción (o --key=POS1[,POS2]). Puede aparecer varias veces y cada tecla puede tener opciones globales (como la nordenación numérica)

Ken Gentle
fuente
77
Desde la página del manual de ordenación: "POS es F [.C] [OPTS], donde F es el número de campo y C la posición del carácter en el campo; ambos son el origen 1". Vea la página del manual para la documentación completa.
Adam Rosenfield
49
También vea la respuesta de andras si no quiere volverse loco.
ron
1
Ambos comentarios anteriores son precisos y aditivos. Gracias caballeros.
Ken Gentle
314

Tenga cuidado sin embargo:

Si desea ordenar el archivo principalmente por el campo 3, y en segundo lugar por el campo 2, desea esto:

sort -k 3,3 -k 2,2 < inputfile

No esto: lo sort -k 3 -k 2 < inputfile que clasifica el archivo por la cadena desde el comienzo del campo 3 hasta el final de la línea (que es potencialmente único).

-k, --key=POS1[,POS2]     start a key at POS1 (origin 1), end it at POS2
                          (default end of line)
andras
fuente
8
Cambiando la vida Gracias.
davidtbernal
2
Whoops! Ahora tengo que arreglar un script porque antes solo vi la primera respuesta anterior ... bueno que aún no he dependido de la salida del script ...
Comodín
¡Agradable! Ahora, ¿qué sucede si quiero que el campo 3 esté ordenado numéricamente y en reversa, mientras que el campo 2 esté ordenado de forma no numérica y normal (ascendente)? :)
Arun
2
@Arun POS se explica al final de la página del manual. Simplemente agregue las opciones de pedido al número de campo como este:sort -k 3,3nr -k 2,2
andras
1
Aargh Qué interfaz contraintuitiva: -k2debería ser -k2,2y una coma final -k2,debería ser 'mágico final de línea predeterminado o lo que sea'.
android.weasel
94

La opción -k es lo que quieres.

-k 1.4,1.5n -k 1.14,1.15n

Usaría las posiciones de caracteres 4-5 en el primer campo (todo es un campo para ancho fijo) y se ordenaría numéricamente como la primera clave.

La segunda clave serían los caracteres 14-15 en el primer campo también.

(editar)

Ejemplo (todo lo que tengo es DOS / cygwin a mano):

dir | \cygwin\bin\sort.exe -k 1.4,1.5n -k 1.40,1.60r

para los datos:

12/10/2008  01:10 PM         1,564,990 outfile.txt

Ordena el listado del directorio por número de mes (pos. 4-5) numéricamente y luego por nombre de archivo (pos. 40-60) a la inversa. Como no hay pestañas, todo es el campo 1 para ordenar.

Clinton Pierce
fuente
Es solo un campo si no hay espacios en blanco en los datos de entrada. Sin embargo, su ejemplo es útil.
Jonathan Leffler
Corrección: si no hay / tabs / en los datos de entrada. En la salida del comando 'dir' de DOS, no hay pestañas.
Clinton Pierce
Los ejemplos sobre cómo usar las opciones (numérico, inverso) son extremadamente útiles, ya que es casi imposible saber cómo usarlos solo desde la página del manual y las otras respuestas no lo mencionaron. Desearía poder hacer +2 por esto. ;)
msb
22

Aquí hay uno para ordenar varias columnas en un archivo csv por orden numérico y de diccionario, columnas 5 y posteriores como orden de diccionario

~/test>sort -t, -k1,1n -k2,2n -k3,3d -k4,4n -k5d  sort.csv
1,10,b,22,Ga
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C

~/test>cat sort.csv
2,3,a,9,C
2,2,b,20,F
2,2,c,19,Gb,hj
2,2,c,19,Gb,hi
2,2,c,19,Ga
2,2,b,22,Ga
1,10,b,22,Ga

Tenga en cuenta que -k1,1n significa numérico que comienza en la columna 1 y termina en la columna 1. Si lo hubiera hecho a continuación, habría concatenado las columnas 1 y 2 haciendo 1,10 ordenado como 110

~/test>sort -t, -k1,2n -k3,3 -k4,4n -k5d  sort.csv
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C
1,10,b,22,Ga
edW
fuente
1
Esta es la mejor respuesta porque muestra cómo usar diferentes interruptores para diferentes columnas
xaxa
12

Creo en tu caso algo como

sort -t@ -k1.1,1.4 -k1.5,1.7 ... <inputfile

Funcionará mejor. @ es el separador de campo, asegúrese de que sea un carácter que no aparece en ninguna parte. entonces su entrada se considera que consta de una columna.

Editar: aparentemente clintp ya dio una respuesta similar, lo siento. Como él señala, las banderas 'n' y 'r' se pueden agregar a cada opción -k ....

Dong Hoon
fuente
Aunque el separador predeterminado acorde a los documentos gnu.org/software/coreutils/manual/html_node/… es el espacio, a veces el recuento de campos no es lo que cabría esperar. Tal vez como otros han dicho aquí debido a la configuración regional LC_CTYPE. En caso de duda, cuente desde el principio de la línea.
Brad Dre
5

Tenga en cuenta que también puede desearse estabilizar la ordenación con el -sinterruptor, de modo que las líneas de igual rango mantengan también su orden relativo original en la salida.

ron
fuente
2

Solo quiero agregar algunos consejos, cuando use sort, tenga cuidado con su configuración regional que afecta el orden de la comparación de teclas. Usualmente uso explícitamente LC_ALL = C para hacer la configuración regional lo que quiero.

jianpx
fuente
LC_ALL = C también puede resultar en una gran aceleración!
mat kelcey