¿Cómo hacer una ordenación personalizada usando la ordenación de Unix?


11

Estoy usando unix sort para ordenar un archivo delimitado por comas con múltiples columnas. Hasta ahora, esto ha funcionado perfectamente para ordenar los datos numéricamente o en orden alfabético:

Archivo de ejemplo antes de cualquier clasificación:

C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

Ordenar el archivo: $ sort -t ',' -k 2,2 -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

Resultado ordenado:

A,Bahamas,Bahamas,Nassau,f,2
A,Canada,QC,Montreal,f,2
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1

Aquí está el problema: quiero ordenar la columna 2 según un orden personalizado, lo que significa que quiero primero a Estados Unidos, luego a Canadá y luego a Bahamas:

Tipo deseado:

A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

¿Hay alguna forma de pasar unix sort a un orden de clasificación personalizado que luego pueda aplicar? Algo como: $ sort -t ',' -k 2,2:'United States, Canada, Bahamas' -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

¡Gracias!


3
Para estos tres valores, desea el orden alfabético inverso. Para el caso general, deberá asignar los nombres a un número de orden de clasificación y luego hacer la clasificación utilizando el número de orden de clasificación. O elija un lenguaje de secuencias de comandos ... Una posibilidad es el joincomando, pero podría terminar con una gran cantidad de clasificación: los archivos de entrada joindeben clasificarse en un orden, y luego volvería a usarlos sortpara colocar los datos en un orden diferente (y perder la columna de orden de clasificación como un paso posterior a la clasificación).
Jonathan Leffler

En su entrada de ejemplo, ¿no debería haber en tlugar de fen la última línea?
Lev Levitsky

Lev: sí, buena captura. Culpa mía; demasiado corte y pegado (mi conjunto de datos real es mucho más grande y accidentalmente tomé las filas incorrectas).

Actualicé la respuesta para que coincida con sus datos.
Lev Levitsky

Respuestas:


8

La otra respuesta y comentario responden la pregunta en general, así es como puede verse una implementación:

$ cat order
Bahamas,3
Canada,2
United States,1

$ cat data
C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

$ sort -t, -k2 data | join -t, -11 -22 order - | sort -t, -k2n -k4,5 -k6r -k7nr | cut -d, -f 3,1,4-7
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

Impresionante, gracias por tu ayuda. Esto funcionó perfectamente!

@jewelia Mejorado una vez más, sedno era realmente necesario aquí.
Lev Levitsky

1

No puedes hacer eso con una especie . En este punto, realmente deberías buscar awk / perl / your-language-of-choice . Sin embargo, puedes evitarlo. Podría, por ejemplo, usar sed para cambiar "Estados Unidos" a 0, "Canadá" a 1 y "Bahamas" a 2, luego hacer una ordenación numérica contra esa columna y luego volver a colocarla. O cambie "Estados Unidos" a "Estados Unidos, 0", etc., ordene la columna adicional y luego deséchela.


0

Acabo de escribir un ayudante llamado csort para que sea más fácil hacer esto. Prefija cada línea con un valor de su elección basado en subcadenas o coincidencias de expresiones regulares dentro de la línea:

$ csort -t, '2=United States' X 2=Canada Y 2=Bahamas Z < tmp.csv | \
sort -t, -k1,1 -k3,3 -k4,4 -k5,5 -k6,6r -k7,7nr
X,A,United States,MA,Boston,f,0
X,B,United States,NY,New York,f,5
X,A,United States,NY,New York,f,1
X,C,United States,WA,Tacoma,f,1
Y,A,Canada,QC,Montreal,f,2
Z,A,Bahamas,Bahamas,Nassau,f,2

La 2=STRnotación significa "coincidir si el segundo campo es igual STR".

Luego, opcionalmente, puede canalizar la salida cut -c3-para eliminar el prefijo.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.