![설명하다](https://linux55.com/image/9733/%EC%84%A4%EB%AA%85%ED%95%98%EB%8B%A4.png)
이 사이트의 첫 번째 질문이므로 잘 설명하지 못하더라도 양해해 주시기 바랍니다. 나도 초보자입니다. Perl 및 Unix 명령줄 항목을 조사했지만 이 문제를 해결하는 방법을 알 수 없습니다.
2개의 파일이 있습니다. 파일 A는 기본 파일이고 10개가 넘는 열과 약 15,000개의 행을 포함하고, 파일 B에는 4개의 열과 약 1500개의 행이 포함되어 있습니다.
파일 B의 각 행을 한 번에 하나씩 가져오고 해당 열을 파일 A의 해당 열과 일치시키고 싶습니다(두 파일의 순서는 다르지만 열 헤더는 동일함). 파일 A에 있는 파일 B의 4개 열이 모두 일치하면 파일 A에서 전체 행을 삭제하고 새 파일(파일 C)에 배치합니다.
예:
파일 A
individual_id study_id.x chromosome g_start gene referencel1hs SampleFile_num id sample_name
54 Baillie2011 4 57497067 na no 612 612 DonorAR2
54 Baillie2011 X 154790187 TMLHE no 612 612 DonorAR2
54 Baillie2011 5 159351203 ADRA1B no 612 612 DonorAR2
54 Baillie2011 13 79259801 na no 612 612 DonorAR2
54 Baillie2011 8 4452925 CSMD1 no 610 610 DonorAH
문서 B
study_id.x sample_name chromosome g_start
Baillie2011 DonorAH 8 4452925
Baillie2011 DonorBC 9 5491376
Baillie2011 DonorAH 8 5829283
Baillie2011 DonorCH 8 5829283
결과:
파일 A
individual_id study_id.x chromosome g_start gene referencel1hs SampleFile_num id sample_name
54 Baillie2011 4 57497067 na no 612 612 DonorAR2
54 Baillie2011 X 154790187 TMLHE no 612 612 DonorAR2
54 Baillie2011 5 159351203 ADRA1B no 612 612 DonorAR2
54 Baillie2011 13 79259801 na no 612 612 DonorAR2
파일C
individual_id study_id.x chromosome g_start gene referencel1hs SampleFile_num id sample_name
54 Baillie2011 8 4452925 CSMD1 no 610 610 DonorAH
답변1
perl -MFatal='open,close' -ali -ne '
if ( @ARGV ) { # FileB readin
if ( $. == 1 ) { push @names, @F; }
else { push @A, join $/, @F; }
print;
} else { # FileA readin
if ( $. == 1 ) {
open FILEC, ">", "FileC.out";
print FILEC $_;
print;
@remap =
map {
my $n = $names[$_];
grep { $n eq $F[$_] } 0 .. $#F;
} 0..$#names;
} else {
my $n = join $/, @F[@remap];
if ( grep { $n eq $_ } @A ) { print FILEC $_; }
else { print; }
}
}
eof and $. = 0;
eof() and close FILEC;
' FileB FileA
설명하다
- Perl 명령줄에 "FileB"와 "FileA"라는 두 개의 파일을 순서대로 제공합니다.
- FileB를 읽는 과정에서 첫 번째 줄인지 다른 줄인지에 따라 두 가지 작업을 수행합니다.
- FileB의 첫 번째 행에 대해 FileB 필드의 이름을 배열에 저장합니다
@names
. - 다른 행의 경우 기본적으로 제공되는
@A
줄바꿈으로 연결된 필드로 배열을 채웁니다 .\n
$/
RS
Perl
두 경우 모두 s 모드-i
에서 FileB를 손실 없이 읽기 위해 이 줄을 STDOUT에 인쇄합니다 .
- FileB의 첫 번째 행에 대해 FileB 필드의 이름을 배열에 저장합니다
- 이제 FileA를 읽을 때 파일을
FILEC
채울 수 있도록 첫 번째 줄에서 쓰기 파일 핸들을 엽니다FileC.out
.- FileB에서 이 줄을 유지하고 싶기 때문에 STDOUT으로 인쇄합니다.
- 또한 헤더가 FileC.out에도 들어가도록 하기 위해 파일 핸들 FILEC에 인쇄합니다.
- 이제 이는 FileB의 필드가 FileA의 필드에 매핑되는 중요한 단계입니다.
- FileA의 첫 번째가 아닌 행에 대해 우리는 이러한 다시 매핑된 필드와 이미 배열에 저장된 FileB 데이터 간의 동일성 검사를 수행합니다
@A
. - 일치하는 항목이 발견되면 이 줄을 FileC.out에 쓰고 FileA에는 쓰지 않습니다. 일치하는 항목이 없으면 FileA는 기록되지만 FileC.out은 기록되지 않습니다.
- 두 파일의 끝에서 줄 카운터를
$.
0으로 재설정하여 첫 번째 줄 동일성 검사가 두 파일 모두에서 수행될 수 있도록 합니다. - 마지막 eof(eof()를 통해 감지됨) 후에 파일 핸들 FILEC를 닫습니다.
- 이 모듈은 이러한 작업을
Fatal.pm
로드open
하고close
자동으로 종료하는 기능을 가지고 있습니다.