4개의 필드(파일 1의 필드 1, 2, 4, 5와 파일 2의 필드 1, 2, 4, 5)를 사용하여 두 파일 File1과 File2(공백으로 구분)를 비교해야 합니다.
논리:
파일 1의 열 1, 2, 4가 파일 2의 열 1, 2, 4와 일치하고 열 5가 일치하지 않으면 파일 1과 파일 2의 두 줄이 연결되어 출력으로 리디렉션됩니다. 따라서 출력 파일에는 File1과 File2의 열 1, 2, 4가 일치하지만 열 5는 일치하지 않는 행만 포함됩니다.
파일 1:
sc2/80 20 . A T 86 PASS N=2 F=5;U=4
sc2/60 55 . G T 76 PASS N=2 F=5;U=4
sc2/68 20 . T C 71 PASS N=2 F=5;U=4
sc2/24 24 . T G 31 PASS N=2 F=5;U=4
파일 2:
sc2/80 20 . A C 80 PASS N=2 F=5;U=4
sc2/60 55 . G C 72 PASS N=2 F=5;U=4
sc2/68 20 . T C 71 PASS N=2 F=5;U=4
sc2/10 24 . T G 31 PASS N=2 F=5;U=4
sc2/40 59 . T G 31 PASS N=2 F=5;U=4
sc2/24 24 . A G 38 PASS N=2 F=5;U=4
산출:
sc2/80 20 . A T 86 PASS N=2 F=5;U=4
sc2/80 20 . A C 80 PASS N=2 F=5;U=4
sc2/60 55 . G T 76 PASS N=2 F=5;U=4
sc2/60 55 . G C 72 PASS N=2 F=5;U=4
저는 이 분야를 처음 접했고 도움을 주셔서 감사합니다.
답변1
당신은 그것을 사용할 수 있습니다 awk
. 스크립트에 다음을 입력하세요 script.awk
.
FNR == NR {
f1[$1,$2,$4] = $0
f1_c14[$1,$2,$4] = 1
f1_c5[$1,$2,$4] = $5
next
}
f1_c14[$1,$2,$4] {
if ($5 != f1_c5[$1,$2,$4]) print f1[$1,$2,$4];
}
f1[$1,$2,$4] {
if ($5 != f1_c5[$1,$2,$4]) print $0;
}
이제 다음과 같이 실행하세요.
$ awk -f script.awk file1 file2
sc2/80 20 . A T 86 PASS N=2 F=5;U=4
sc2/80 20 . A C 80 PASS N=2 F=5;U=4
sc2/60 55 . G T 76 PASS N=2 F=5;U=4
sc2/60 55 . G C 72 PASS N=2 F=5;U=4
스크립트는 다음과 같이 작동합니다. 이 블록은 , 및 3개의 배열을 f1
생성 f1_c14
합니다 f1_c5
. f1
file1의 열 1, 2, 4의 내용을 사용하여 인덱싱된 배열에 있는 file1의 모든 행을 포함합니다. f1_c14
은 동일한 인덱스(1, 2, 4의 내용)와 값을 가진 또 다른 배열입니다 1
. 세 번째 배열은 처음 2개와 동일한 인덱스를 사용하며 해당 값은 file1의 열 5 값입니다.
FNR == NR {
f1[$1,$2,$4] = $0
f1_c14[$1,$2,$4] = 1
f1_c5[$1,$2,$4] = $5
next
}
다음 블록은 file1
열 1, 2, 4가 의 열과 일치하는 경우 첫 번째 파일의 행을 인쇄하는 역할을 담당합니다 file2
.그리고AND의 5번째 열이 일치하지 않으면 file1
해당 행만 인쇄됩니다.file1
file2
f1_c14[$1,$2,$4] {
if ($5 != f1_c5[$1,$2,$4]) print f1[$1,$2,$4];
}
세 번째 블록은 열 1, 2, 4에 해당하는 배열의 관련 행을 인쇄하는 역할을 합니다. 다시 말하지만, 열 5가 일치하지 않는 경우에만 인쇄됩니다 file2
.f1
file2
f1[$1,$2,$4] {
if ($5 != f1_c5[$1,$2,$4]) print $0;
}
예
위의 스크립트를 다음과 같이 실행하세요.
$ awk -f script.awk file1 file2
sc2/80 20 . A T 86 PASS N=2 F=5;U=4
sc2/80 20 . A C 80 PASS N=2 F=5;U=4
sc2/60 55 . G T 76 PASS N=2 F=5;U=4
sc2/60 55 . G C 72 PASS N=2 F=5;U=4
column
다음을 사용하여 출력을 약간 정리할 수 있습니다 .
$ awk -f script.awk file1 file2 | column -t
sc2/80 20 . A T 86 PASS N=2 F=5;U=4
sc2/80 20 . A C 80 PASS N=2 F=5;U=4
sc2/60 55 . G T 76 PASS N=2 F=5;U=4
sc2/60 55 . G C 72 PASS N=2 F=5;U=4
어떻게 작동하나요?
FNR == NRawk
이는 특정 방식으로 파일을 반복하는 기능을 활용합니다 . 여기에서는 파일을 반복하고 있으며 첫 번째 파일의 한 줄에 있을 때 file
해당 줄의 특정 코드 블록을 실행하려고 합니다 file1
.
이 예는 FNR == NR
2개의 시뮬레이션 파일을 제공할 때 수행되는 작업을 보여줍니다. 그 중 하나에는 4개의 행이 있고 다른 하나에는 5개의 행이 있습니다.
$ awk 'BEGIN {print "NR\tFNR\tline"} {print NR"\t"FNR"\t"$0}' \
<(seq 1 4) <(seq 1 5)
NR FNR line
1 1 1
2 2 2
3 3 3
4 4 4
5 1 1
6 2 2
7 3 3
8 4 4
9 5 5
기타 블록
다른 블록 f1_c14[$1,$2,$4]
AND는 f1[$1,$2,$4]
해당 배열 요소의 값에 값이 있는 경우에만 실행됩니다.
답변2
이것이 Perl의 솔루션입니다. 다음 코드를 파일에 저장하고 스크립트로 실행해야 합니다(아래 참조).
#!/usr/bin/perl
$file1 = '/path/to/file1';
$file2 = '/path/to/file2';
open $f1,'<',$file1;
open $f2,'<',$file2;
while(<$f1>){
($c1,$c2,$c4,$c5) = (split / /)[0,1,3,4]; #get relevant columns in file 1
$lines_dictionary{"$c1 $c2 $c4"}="$c5---$_"; #create a hash entry keyed by the relevant columns
}
while(<$f2>){
($c1,$c2,$c4,$c5) = (split / /)[0,1,3,4]; #get relevant columns in file 2
if(exists $lines_dictionary{"$c1 $c2 $c4"}){ #if a line with similar columns was seen in file 1
($file1_c5,$file1_line) = split /---/,$lines_dictionary{"$c1 $c2 $c4"}; #parse the hash entry this line in file 1
if($file1_c5 -ne $c5){ #if column 5 of file 2 doesn't match column 5 of file 1
print "${file1_line}$_\n"; #we only need one extra newline as the lines read from the files have trailing ones.
}
}
}
close $f1;
close $f2;
텍스트 편집기를 사용하여 이 스크립트를 파일에 붙여넣고 $file1
및 $file2
변수를 수정하여 파일의 실제 위치를 반영한 후 다음을 수행하여 스크립트를 실행 가능하게 만듭니다.
$ chmod +x /path/to/script
마지막으로 스크립트를 호출합니다.
$ /path/to/script
부인 성명
- 이 코드는 테스트되지 않았습니다.
- 이 코드에서는 "---" 패턴이 열 5에 나타날 가능성이 없다고 가정합니다.
- 이 코드는 파일 1의 행이 고유하다고 가정합니다(즉, 각 행에 "column1, column2, column4"의 서로 다른 조합이 있음). 관련 열에 동일한 데이터를 포함하는 여러 행(연속적이지 않아도 됨)이 있는 경우 스크립트는 해당 행의 마지막 행(파일의 맨 아래 행)을 사용합니다.