J'ai deux fichiers avec environ 12900 et 4400 entrées respectivement, que je veux joindre. Les fichiers contiennent des informations sur l'emplacement de toutes les stations d'observation météorologique terrestres du monde entier. Le plus gros fichier est mis à jour toutes les deux semaines, et le plus petit une fois par an environ. Les fichiers originaux peuvent être trouvés ici ( http://www.wmo.int/pages/prog/www/ois/volume-a/vola-home.htm et http://weather.rap.ucar.edu/surface/ stations.txt ). Les fichiers que j'ai sont déjà manipulés par moi avec un script mixte awk, sed et bash. J'utilise les fichiers pour visualiser les données à l'aide du package GEMPAK, qui est disponible gratuitement auprès d'Unidata. Le plus gros fichier fonctionnera avec GEMPAK, mais pas uniquement avec sa pleine capacité. Pour cela, une jointure est nécessaire.
Le fichier 1 contient des informations de localisation pour les stations d'observation météorologique, où les 6 premiers chiffres sont l'identifiant unique de la station. Les différents paramètres (numéro de station, nom de station, code de pays, longitude de latitude et altitude de station) sont définis uniquement par sa position sur la ligne, c'est-à-dire sans onglets.
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
Le fichier 2 contient l'identifiant unique du fichier 1 et un deuxième identifiant à 4 caractères (localisateur 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
Je veux joindre les deux fichiers, afin que le fichier résultant ait l'identifiant à 4 caractères dans les 4 premières positions de la ligne, c'est-à-dire que l'identifiant devrait remplacer les 4 espaces.
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
Est-il possible d'accomplir cette tâche avec un script bash et / ou awk?
la source
Réponses:
la source
Quelques-uns d'entre nous voulaient voir si nous pouvions résoudre ce problème en utilisant
join
uniquement. Ceci est ma tentative de le faire. Puisqu'il fonctionne partiellement, @Terdon me doit un dîner 8-).La commande
Exemple
Détails
Ce qui précède utilise à peu près toutes les options disponibles,
join
ce qui indique à mon instinct que nous l'utilisons mal, comme dans un certain type de Frankenstein, mais nous apprenons tous ici, donc c'est OK ... Je suppose.Le commutateur
-a1
indique à join d'inclure toutes les lignes qui n'ont pas de correspondance correspondante de file2 dans file1. Voici donc ce qui pousse ces lignes à s'afficher:Les
-1 1
et-2 1
disent sur quelles colonnes joindre les lignes des 2 fichiers, principalement leurs 1ères colonnes. Le-o ...
dit quelles colonnes des 2 fichiers afficher et dans quel ordre.Le
-e "N/A"
dit d'utiliser la chaîne "N / A" comme valeur d'espace réservé pour imprimer les champs qui sont considérés comme vides parjoin
.Les 2 derniers arguments alimentent les 2 fichiers
file1
etfile2
sont triés dans la commande join.Veuillez être gentil, car c'est un travail en cours et nous essayons de montrer comment on pourrait résoudre ce type de problème en utilisant la
join
commande, car cela semble être le type de problème auquel il était destiné.Problèmes en suspens
3e colonne
Le principal est de savoir comment composer avec la 3e colonne, car il s'agit d'un mélange de valeurs de 1 mot et de 2 mots. Cela semble être une pierre d'achoppement majeure
join
et je ne peux pas trouver un moyen de le contourner. Tout conseil serait apprécié.Espacement
Tout l'espacement d'origine est perdu avec
join
et je ne vois pas non plus de moyen de le garder. Cejoin
n'est donc peut-être pas la bonne façon de traiter ces types de problèmes après tout.Semble fonctionner cependant?
Après beaucoup de flexions avec la ligne de commande, la solution générale est là, donc cela semble fonctionner au moins partiellement, donc cela pourrait être utilisé au cœur d'une solution, puis utiliser d'autres outils tels que
awk
etsed
pour la nettoyer . Cela soulève cependant la question: "Si vous le nettoyez avecawk
& desed
quelque manière que ce soit, alors vous pourriez aussi bien les utiliser directement?".la source
join
alors maintenant Internet a celui-ci. 8-)Cela devrait être possible en utilisant
join
mais je ne sais pas comment faire pour imprimer correctement les espaces et les champs vides. Quoi qu'il en soit, ce petit script Perl fera l'affaire:Enregistrez-le sous
foo.pl
et exécutez comme suit:la source
-o
fonctionnalité auparavant, ne fonctionnant pas comme je m'y attendais.-o
et-e
mais je n'ai pas pu l'obtenir pour imprimer des lignes qui n'avaient pas d'entrée dans file2. Bonne chance, je serais intéressé de savoir si c'est possible.Bash fera l'affaire.
Voir cette réponse SO pour les détails de ce qui se passe avec le "hachage" Bash 4 supporte nativement les tableaux associatifs, mais cela devrait fonctionner en 3 + 4 (peut-être 2?)
Vous devrez peut-être couper la ligne à partir du fichier 1 pour obtenir votre mise en forme.
la source
Voici un moyen simple de le faire avec
join
(+ quelques autres outils) et de conserver l'espacement. Les deux fichiers semblent être triés par numéro de station, donc aucun tri supplémentaire n'est nécessaire:La partie avant le tuyau est très similaire à ce que slm a utilisé dans sa réponse, donc je ne vais pas le revoir. La seule différence est que j'utilise
-e " "
- une chaîne de quatre espaces en remplacement des champs d'entrée manquants et-o 2.2
pour sortir uniquement le 2ème champ du fichier2 Produitdonc
join -j1 -a1 -o 2.2 -e " " file1 file2
une colonne de quatre caractères (elle n'est pas visible ci-dessous mais il n'y a rien après EK ** et les lignes vides sont en fait quatre espaces):nous avons ensuite
paste
ceci (en utilisant l'espace comme délimiteur) dans file1 dont nous avonscut
les 5 premiers caractères.| paste -d' ' - <(cut -c6- file1)
Résultat final:
la source