Tengo dos archivos con aproximadamente 12900 y 4400 entradas respectivamente, que quiero unir. Los archivos contienen información de ubicación para todas las estaciones de observación meteorológica terrestres en todo el mundo. El archivo más grande se actualiza quincenalmente y el más pequeño una vez al año más o menos. Los archivos originales se pueden encontrar aquí ( http://www.wmo.int/pages/prog/www/ois/volume-a/vola-home.htm y http://weather.rap.ucar.edu/surface/ estaciones.txt ). Los archivos que tengo ya están manipulados por mí con un script mixto de awk, sed y bash. Utilizo los archivos para visualizar datos utilizando el paquete GEMPAK, que está disponible gratuitamente en Unidata. El archivo más grande funcionará con GEMPAK, pero solo no con toda su capacidad. Para esto se necesita una unión.
El archivo 1 contiene información de ubicación de las estaciones de observación meteorológica, donde los primeros 6 dígitos son el identificador único de la estación. Los diferentes parámetros (número de estación, nombre de estación, código de país, longitud de latitud y elevación de estación) se definen solo por su posición en la línea, es decir, sin pestañas.
060090 AKRABERG FYR DN 6138 -666 101
060100 VAGA FLOGHAVN DN 6205 -728 88
060110 TORSHAVN DN 6201 -675 55
060120 KIRKJA DN 6231 -631 55
060130 KLAKSVIK HELIPORT DN 6221 -656 75
060160 HORNS REV A DN 5550 786 21
060170 HORNS REV B DN 5558 761 10
060190 SILSTRUP DN 5691 863 0
060210 HANSTHOLM DN 5711 858 0
060220 TYRA OEST DN 5571 480 43
060240 THISTED LUFTHAVN DN 5706 870 8
060290 GROENLANDSHAVNEN DN 5703 1005 0
060300 FLYVESTATION AALBORG DN 5708 985 13
060310 TYLSTRUP DN 5718 995 0
060320 STENHOEJ DN 5736 1033 56
060330 HIRTSHALS DN 5758 995 0
060340 SINDAL FLYVEPLADS DN 5750 1021 28
El archivo 2 contiene el identificador único en el archivo 1 y un segundo identificador de 4 caracteres (localizador de la OACI).
060100 EKVG
060220 EKGF
060240 EKTS
060300 EKYT
060340 EKSN
060480 EKHS
060540 EKHO
060600 EKKA
060620 EKSV
060660 EKVJ
060700 EKAH
060780 EKAT
Quiero unir los dos archivos, para que el archivo resultante tenga el identificador de 4 caracteres en las primeras 4 posiciones en la línea, es decir, el identificador debe reemplazar los 4 espacios.
060090 AKRABERG FYR DN 6138 -666 101
EKVG 060100 VAGA FLOGHAVN DN 6205 -728 88
060110 TORSHAVN DN 6201 -675 55
060120 KIRKJA DN 6231 -631 55
060130 KLAKSVIK HELIPORT DN 6221 -656 75
060160 HORNS REV A DN 5550 786 21
060170 HORNS REV B DN 5558 761 10
060190 SILSTRUP DN 5691 863 0
060210 HANSTHOLM DN 5711 858 0
EKGF 060220 TYRA OEST DN 5571 480 43
EKTS 060240 THISTED LUFTHAVN DN 5706 870 8
060290 GROENLANDSHAVNEN DN 5703 1005 0
EKYT 060300 FLYVESTATION AALBORG DN 5708 985 13
060310 TYLSTRUP DN 5718 995 0
060320 STENHOEJ DN 5736 1033 56
060330 HIRTSHALS DN 5758 995 0
EKSN 060340 SINDAL FLYVEPLADS DN 5750 1021 28
¿Es posible realizar esta tarea con algún script bash y / o awk?
fuente
Respuestas:
fuente
Algunos de nosotros queríamos ver si solo podíamos resolver este problema
join
. Este es mi intento de hacer eso. Como funciona parcialmente, @Terdon me debe una cena 8-).El comando
Ejemplo
Detalles
Lo anterior está haciendo uso de casi todas las opciones disponibles
join
que le dicen a mi instinto que lo estamos usando mal, como en algún tipo de forma de Frankenstein, pero todos estamos aprendiendo aquí, así que está bien ... supongo.El modificador
-a1
le dice a join que incluya cualquier línea que no tenga una coincidencia correspondiente del archivo2 en el archivo1. Entonces, esto es lo que está impulsando estas líneas para mostrarse:Los
-1 1
y-2 1
están diciendo en qué columnas unir las líneas de los 2 archivos, principalmente sus primeras columnas. El-o ...
dice qué columnas de los 2 archivos para mostrar y en qué orden.El
-e "N/A"
dice usar la cadena "N / A" como un valor de marcador de posición para imprimir para los campos que se consideran vacíosjoin
.Los últimos 2 argumentos están alimentando los 2 archivos,
file1
yfile2
según lo ordenado en el comando de unión.Sea amable, ya que este es un trabajo en progreso y estamos tratando de demostrar cómo se resolvería este tipo de problema utilizando el
join
comando, ya que este parece ser el tipo de problema para el que fue diseñado.Cuestiones pendientes
3ra columna
La principal es cómo lidiar con la tercera columna, ya que es una combinación de valores de 1 palabra y 2 palabras. Esto parece ser un obstáculo importante
join
y no puedo encontrar una forma de evitarlo. Cualquier orientación sería apreciada.Espaciado
Se pierde todo el espacio original
join
y tampoco veo una manera de mantenerlo. Porjoin
lo tanto, podría no ser la forma correcta de lidiar con este tipo de problemas después de todo.Aunque parece funcionar?
Después de mucho doblar con la línea de comando, la solución general está ahí, por lo que parece que puede funcionar al menos parcialmente, por lo que podría usarse en el núcleo de una solución y luego usar otras herramientas como
awk
ysed
para limpiarla. . "Si usted está limpiando para arriba con: la pregunta, sin embargo esto planteaawk
ysed
de cualquier manera, entonces puede ser que también acaba de utilizar directamente?".fuente
join
lo que ahora Internet tiene esta. 8-)Esto debería ser posible usando
join
pero no puedo encontrar la manera de imprimir espacios y campos vacíos correctamente. De todos modos, este pequeño script de Perl hará el truco:Guarde esto como
foo.pl
y ejecute lo siguiente:fuente
-o
función antes, no funcionaba como era de esperar.-o
y-e
no pude conseguir que imprima líneas que no tenían entrada en el archivo2. Buena suerte, me interesaría saber si es posible.Bash lo hará.
Vea esta respuesta SO para conocer los detalles de lo que está sucediendo con el "hash". Bash 4 admite la matriz asociativa de forma nativa, pero esto debería funcionar en 3 + 4 (¿tal vez 2?)
Es posible que deba recortar la línea del archivo1 para obtener el formato.
fuente
Aquí hay una manera simple de hacerlo
join
(+ un par de herramientas más) y preservar el espacio. Parece que ambos archivos están ordenados por número de estación, por lo que no se necesita una clasificación adicional:La parte anterior a la tubería es muy similar a la que usó slm en su respuesta, por lo que no volveré a analizarla. La única diferencia es que estoy usando
-e " "
: una cadena de cuatro espacios como reemplazo de los campos de entrada faltantes y-o 2.2
para generar solo el segundo campo del archivo2Entonces
join -j1 -a1 -o 2.2 -e " " file1 file2
produce una columna de cuatro caracteres de ancho (no es visible a continuación, pero no hay nada después de EK ** y las líneas vacías son en realidad cuatro espacios):luego
paste
esto (usando el espacio como delimitador) al archivo1 del cual tenemoscut
los primeros 5 caracteres| paste -d' ' - <(cut -c6- file1)
Resultado final:
fuente