![고유 식별자를 사용하여 두 파일 연결](https://linux55.com/image/50101/%EA%B3%A0%EC%9C%A0%20%EC%8B%9D%EB%B3%84%EC%9E%90%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC%20%EB%91%90%20%ED%8C%8C%EC%9D%BC%20%EC%97%B0%EA%B2%B0.png)
각각 약 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
일종의 프랑켄슈타인 방식처럼 사용하는 것이 잘못되었다고 직감적으로 알려주지만, 우리는 모두 배우기 위해 여기에 있으므로 중요하지 않습니다..... 내 생각에는.
이 스위치는 -a1
file2에 해당 일치 항목이 없는 모든 행을 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
명령을 사용하여 이러한 문제를 해결하는 방법을 보여 주려고 노력하고 있습니다. 이는 해결하려는 문제 유형인 것 같습니다.
중요한 문제
3열
가장 큰 문제는 세 번째 열이 1단어 값과 2단어 값이 혼합되어 있기 때문에 어떻게 해야 하느냐는 것입니다. 이것은 큰 걸림돌인 것 같고
join
나는 그 문제를 해결할 방법을 찾을 수 없습니다. 어떤 지침이라도 대단히 감사하겠습니다.간격
원래 간격이 모두 손실되었으며
join
이를 보존할 방법을 찾지 못했습니다. 따라서 이것은join
이러한 유형의 문제를 처리하는 올바른 방법이 아닐 수도 있습니다.작동하는 것 같나요?
명령줄을 많이 사용한 후에는 일반적인 솔루션이 있으므로 적어도 부분적으로 작동할 수 있는 것처럼 보이므로 이를 솔루션의 핵심으로 사용한 다음 및 같은 다른 도구를 사용하여
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.2
file2의 두 번째 필드만 출력하여 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