Shell-Script

連接具有唯一標識符的兩個文件

  • April 29, 2015

我有兩個文件,分別包含大約 12900 和 4400 個條目,我想加入它們。這些文件包含全球所有陸基氣象觀測站的位置資訊。最大的文件每兩週更新一次,較小的文件一年左右更新一次。可以在此處找到原始文件(http://www.wmo.int/pages/prog/www/ois/volume-a/vola-home.htmhttp://weather.rap.ucar.edu/surface/站.txt)。我已經使用一些混合的 awk、sed 和 bash 腳本來操作我擁有的文件。我使用這些文件使用 GEMPAK 包來視覺化數據,該包可從 Unidata 免費獲得。最大的文件可以與 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 中的唯一標識符和第二個 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 個字元的標識符,即標識符應該替換 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 腳本來完成這項任務?

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

我們中的一些人想看看我們是否可以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這告訴我的直覺我們用錯了,就像某種科學怪人的方式一樣,但我們都在這裡學習,所以沒關係……我猜。

該開關-a1告訴 join 包括在 file1 中沒有來自 file2 的相應匹配的任何行。所以這就是驅動這些行顯示的原因:

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

-1 1-2 1表示要加入 2 個文件中的行的列,主要是它們的第 1 列。這-o ...是說要顯示 2 個文件中的哪些列以及按什麼順序顯示。

說使用字元串“ -e "N/A"N/A”作為佔位符值來列印被認為是空的欄位join

最後 2 個參數提供 2 個文件,file1&file2排序到 join 命令中。

請善待,因為這是一項正在進行的工作,我們正在嘗試展示如何使用該命令解決此類問題join,因為這似乎是它所要解決的問題類型。

顯著的問題

  1. 第三欄

主要的問題是如何處理第 3 列,因為它是 1 個單詞和 2 個單詞值的混合。這似乎是一個主要的絆腳石join,我想不出辦法。任何指導將不勝感激。 2. 間距

所有原始間距都失去了join,我也沒有辦法保留它。因此join,畢竟可能不是處理這些類型問題的正確方法。 3. 似乎工作?

在使用命令行多次彎曲之後,通用解決方案就在那裡,所以這似乎至少可以部分工作,所以這可以用作解決方案的核心,然後使用其他工具,例如awksed清理它. awk然而,這引出了一個問題:“如果你用&任何方式清理它sed,那麼你還不如直接使用它們?”。

引用自:https://unix.stackexchange.com/questions/90214