Tengo el siguiente archivo:
cat fileA.txt
seattle 1991 west
atlanta 1993 west
turlock 1998 west
marysville 2004 south
newyork 2007 north
canada 2004 west
Y el segundo archivo se ve así:
cat fileB.txt
popular
someWhatPopular
boring
popular
popular
popular
Me gustaría obtener el siguiente resultado sobre fileB.txt
:
popular popular popular someWhatPopular boring popular
Básicamente, estoy intentando ordenar fileB.txt
en fileA.txt
la tercera columna.
Probé el siguiente código:
#!/bin/bash
sort -s -k3,3 fileA.txt fileB.txt
Pero no funcionó. ¿Alguna sugerencia? Estoy bastante abierto a cualquier cosa que no requiera codificación. bash/awk/sed,etc.
Respuesta1
Este es un problema de estructura de datos más que de Linux. Necesita una entrada común (clave) en ambas tablas para vincularlas, igual que en cualquier 'base de datos' y es una buena práctica mantener una clave única en la primera columna de cualquier tabla de datos. Luego puedes ordenar y vincular el contenido de tu corazón.
Tomando algo como el mapeo @glennjackman, defines la clave de mapeo como norte, sur, etc.
1 south somewhatPopular
2 west popular
3 north boring
4 east unexplored
en un archivo llamado archivo popularity
. Modificar fileA
para incluir una clave única
1 seattle 1991 west
2 atlanta 1993 west
3 turlock 1998 west
4 marysville 2004 south
5 newyork 2007 north
6 canada 2004 west
luego puede manipular estos archivos ingresándolos join
en la clave seleccionada (en su caso, la columna 2 en popularity
se asigna a la columna 4 en fileA
) pero join
necesita que ambos archivos estén ordenados en el campo clave, por lo que
join -1 4 -2 2 <(sort -k4 fileA) <(sort -k2 popularity) | sort -k2 | awk '{print $6}'
popular
popular
popular
somewhatPopular
boring
popular
Un enfoque un poco duro, pero le brinda mayor flexibilidad.
Rompe el comando anterior en cada tubería y verás lo que hace cada paso.
Editar: Explicación dejoin -1 4 -2 2 # its in the man pages
Esto le indica join
que mire la cuarta columna de la tabla 1 (-1 4) y encuentre valores coincidentes en la segunda columna de la tabla 2 (-2 2).
join
luego compone columnas de las dos tablas en una sola tabla pero solo incluye la columna clave (norte, etc.) una vez. Mire la salida de
join -1 4 -2 2 <(sort -k4 fileA) <(sort -k2 popularity)
y debería ser más claro
Debido a que tuvimos que ordenar las tablas de datos para que join
funcionara, luego
| sort -k2
la tabla combinada para volver a colocarlos en su orden original.
La columna que desea es la columna 6 en la tabla combinada, por lo que simplemente
| awk '{print $6}'
a la salida estándar.
Respuesta2
Puede intentar paste
juntar los dos archivos de "tabla", canalizar la salida a sort
y luego cut
conservar solo la cuarta columna.
Un intento no probado (teléfono celular en este momento) sería algo así como
paste fileA fileB | sort -s -k3,3 | cut -f4
Respuesta3
Puede obtener el mapeo alfabético con
paste <(awk '{print $NF}' fileA.txt | sort -u) <(sort -u fileB.txt)
north boring
south popular
west someWhatPopular
Y luego se puede producir una forma del resultado deseado con awk:
awk '
NR==FNR {map[$1] = $2; next}
{print map[$NF]}
' <(paste <(awk '{print $NF}' fileA.txt | sort -u) <(sort -u fileB.txt)) fileA.txt
someWhatPopular
someWhatPopular
someWhatPopular
popular
boring
someWhatPopular