一意の識別子を使用した2つのファイルの関連付け

一意の識別子を使用した2つのファイルの関連付け

それぞれ約12900個と4400個のエントリを含む2つのファイルがあり、それらを組み合わせたいと思います。このファイルには、世界中のすべての陸上気象観測所の位置情報が含まれています。最大のファイルは2週間ごとに更新され、小さなファイルは約1年ごとに更新されます。元のファイルはこちら(http://www.wmo.int/pages/prog/www/ois/volume-a/vola-home.htmそして http://weather.rap.ucar.edu/surface/stations.txt)。私はawk、sed、bashスクリプトを混在させてファイルを操作しました。 Unidataから無料で入手可能なGEMPAKパッケージを使用してデータを視覚化するためにこのファイルを使用しました。 GEMPAKでは最大のファイルを使用できますが、フル機能は使用できません。これには会員登録が必要です。

ファイル1には気象観測所の位置情報が含まれており、最初の6桁はサイト固有の識別子です。さまざまなパラメータ(サイト番号、サイト名、国コード、緯度、経度、サイト高度)は、タブ文字なしの行の位置によってのみ定義されます。

         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

ファイル2には、ファイル1の一意の識別子と2番目の4桁の識別子(ICAOロケータ)が含まれています。

060100 EKVG
060220 EKGF
060240 EKTS
060300 EKYT
060340 EKSN
060480 EKHS
060540 EKHO
060600 EKKA
060620 EKSV
060660 EKVJ
060700 EKAH
060780 EKAT

結果ファイルが行の最初の4つの場所に4文字の識別子を持つように、これら2つのファイルをリンクしたいと思います。つまり、識別子は4つのスペースを置き換える必要があります。

         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

これを行うには、いくつかのbashスクリプトおよび/またはawkスクリプトを使用できますか?

答え1

awk 'BEGIN { while(getline < "file2" ) { codes[$1] = $2 } }
     { printf "%4s%s\n", codes[$1], substr($0, 5) }' file1

答え2

私たちのいくつかはjoinちょうど。これが私の試みです。部分的に働くので、@Terdonは私に夕食を借りています8-)。

注文する

$ join -a1 -1 1 -2 1 -o 2.2 1.1 1.2 1.3 1.4 1.5 1.6 1.7 -e "N/A" \
     <(sort file1) <(sort file2)

はい

$ join -a1 -1 1 -2 1 -o 2.2 1.1 1.2 1.3 1.4 1.5 1.6 1.7 -e "N/A" <(sort file1) <(sort file2) | column -t
N/A   060090  AKRABERG          FYR         DN    6138  -666  101
EKVG  060100  VAGA              FLOGHAVN    DN    6205  -728  88
N/A   060110  TORSHAVN          DN          6201  -675  55    N/A
N/A   060120  KIRKJA            DN          6231  -631  55    N/A
N/A   060130  KLAKSVIK          HELIPORT    DN    6221  -656  75
N/A   060160  HORNS             REV         A     DN    5550  786
N/A   060170  HORNS             REV         B     DN    5558  761
N/A   060190  SILSTRUP          DN          5691  863   0     N/A
N/A   060210  HANSTHOLM         DN          5711  858   0     N/A
EKGF  060220  TYRA              OEST        DN    5571  480   43
EKTS  060240  THISTED           LUFTHAVN    DN    5706  870   8
N/A   060290  GROENLANDSHAVNEN  DN          5703  1005  0     N/A
EKYT  060300  FLYVESTATION      AALBORG     DN    5708  985   13
N/A   060310  TYLSTRUP          DN          5718  995   0     N/A
N/A   060320  STENHOEJ          DN          5736  1033  56    N/A
N/A   060330  HIRTSHALS         DN          5758  995   0     N/A
EKSN  060340  SINDAL            FLYVEPLADS  DN    5750  1021  28

詳細

上記は、利用可能なほとんどすべてのオプションを使用して、ある種のjoinフランケンシュタイン方式のように使用するのが間違っていると直感的に教えてくれますが、私たちはすべて学ぶためにここにいるので重要ではありません.....私の考えでは。

このスイッチは、-a1file2に対応する一致がないすべての行をfile1に含めるようにJoinに指示します。これが次の行の表示を駆動することです。

N/A   060330  HIRTSHALS         DN          5758  995   0     N/A

2つのファイルの行がどの列に関連付けられているかを示します。主に最初の列です-1 1。 2つのファイルのどの列をどの順序で表示するかを-2 1示します。-o ...

-e "N/A"空であると見なされるフィールドを印刷するために文字列「N / A」がプレースホルダ値として使用されることを示しますjoin

最後の2つのパラメータは2つのファイルを入力し、file1順番にfile2結合コマンドに入れます。

これは進行中なので、このjoinコマンドを使用してこれらの問題を解決する方法を紹介しようとしています。これは解決したい問題の種類のようです。

重要な問題

  1. 3列

    最大の問題は、3番目の列が1単語の値と2単語の値が混在しているために何をすべきかということです。これは大きな障害と思われ、join私はその問題を解決する方法を見つけることができません。どんな指針でも大変感謝いたします。

  2. 間隔

    もともとギャップがすべて失われ、joinそれを保存する方法が見つかりませんでした。したがって、これはjoinこの種の問題を処理する正しい方法ではないかもしれません。

  3. うまくいくと思いますか?

    コマンドラインを大量に使用した後は、一般的な解決策があるため、少なくとも部分的に機能できるように見えるので、それを解決策のコアとして使用してから、その他のツールを使用して整理してawkくださいsed。しかし、これは「awk&どのような方法で掃除したら、sed単に使用するのが良いでしょうか?」という質問をします。

答え3

これしなければならないうまくいきますjoinが、空白と空白のフィールドを正しく印刷する方法がわかりません。とにかく、この小さなPerlスクリプトはトリックを行います。

#!/usr/bin/env perl

## Open file2, the one that contains the codes
## it is expected to be the 1st argument given to the script.
open($a,"$ARGV[0]"); 

## Read the number<=>code pairs into a hash (an associative array)
## called 'k'
while (<$a>) {
    chomp; @f=split(/\s+/); $k{$f[0]}=$f[1];
}

## Open file1, the one that contains the data
## it is expected to be the 2nd argument given to the script.
open($b,"$ARGV[1]"); 
## Go through the file
while (<$b>) {
    ## Split each line at white space into the array @f
    @f=split(/\s+/);  

    ## $f[1] is the 6 digit number that defines the different stations.
    ## If this number has an entry in the hash %k, if it was found
    ## in file2, replace the first 4 spaces with its value from the hash.
    s/^\s{4}/$k{$f[1]}/ if defined($k{$f[1]});

    ## Print each line of the file
    print; 
}

別の名前で保存し、foo.pl次のように実行します。

$ perl foo.pl file2 file1
         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

答え4

join以下は、(+追加ツール)を使用して間隔を維持および維持する簡単な方法です。どちらのファイルもステーション番号でソートされているため、追加のソートは必要ありません。

join -j1 -a1 -o 2.2 -e "    " file1 file2 | paste -d' ' - <(cut -c6- file1)

パイプの前部は非常に似ています。持続可能な開発管理使用彼の答えだから私は再びそれに入らないでしょう。唯一の違いは、-e " "欠落している入力フィールドを置き換えるために4つの空白文字列を使用し、-o 2.2file2の2番目のフィールドのみを出力して4文字の幅の列を生成する
ことですjoin -j1 -a1 -o 2.2 -e " " file1 file2(下には表示されませんが、EKの後には何も表示されません) **と空白行は実際には4つのスペースです。)

心電図







心電図成長因子
EKTS

アイキット



EKSN

次に、スペースを区切り文字としてfile1に移動して最初の5文字をpaste​​取得します。最終結果:cut| paste -d' ' - <(cut -c6- file1)

         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

関連情報