고유 식별자를 사용하여 두 파일 연결

고유 식별자를 사용하여 두 파일 연결

각각 약 12900개와 4400개의 항목이 포함된 두 개의 파일이 있고 이를 결합하고 싶습니다. 이 파일에는 전 세계 모든 육상 기상 관측소의 위치 정보가 포함되어 있습니다. 가장 큰 파일은 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의 고유 식별자와 두 번째 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 스크립트를 사용할 수 있습니까?

답변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열

    가장 큰 문제는 세 번째 열이 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의 두 번째 필드만 출력하여 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

관련 정보