2개의 입력 파일이 있습니다. 의 모든 행은 File1
의 모든 행과 비교되어야 합니다 File2
.
논리는 다음과 같습니다.
of가 일치하지 않으면
Column1
(그 아래의 모든 값)File1
전체 줄이 출력 파일에 인쇄됩니다. 마찬가지로 의 각 값은 의 각 값과 비교됩니다.Column1
File2
File1
Column1
Column1
File2
두 파일 모두에 일치하는 항목이 있고
Column1
값이 해당 값보다 크거나 작은 경우 전체 줄을 인쇄하고 이와 같이 모든 줄을 비교할 수 있습니다.Column2
File1
N+10
N-10
N
Column2
File2
File1
File2
File1
:
Contig1 23
Contig1 42
Contig2 68
Contig3 89
Contig3 102
Contig7 79
File2
:
Contig1 40
Contig1 49
Contig3 90
Contig2 90
Contig20 200
Contig1 24
예상 출력:
Contig2 68
Contig3 102
Contig7 79
어떤 솔루션이든, 심지어 awk
없더라도 sed
가능합니다.
비슷한 질문을 찾았지만 어떻게 해야 할지 잘 모르겠습니다.
코드는 다음과 같습니다.
`NR==FNR {
lines[NR,"col1"] = $1
lines[NR,"col2"] = $2
lines[NR,"line"] = $0
next
}
(lines[FNR,"col1"] != $1) {
print lines[FNR,"line"]
next
}
(lines[FNR,"col2"]+10 < $2 || lines[FNR,"col2"]-10 > $2) {
print lines[FNR,"line"]
}' file1 file2`
답변1
아래 스크립트는 다음을 수행합니다. 제 생각에는 이것이 여러분이 원하는 것입니다.
- file1의 contig가 file2에 없으면 해당 contig에 대한 모든 행을 인쇄합니다.
- file2에 존재하는 경우 file1의 각 값에 대해 -10 이상이거나 file2 -10의 해당 contig 값보다 크거나 file2 +10의 값보다 큰 경우에만 인쇄합니다.
#!/usr/bin/env perl
my (%file1, %file2);
## read file1, the 1st argument
open(F1,"$ARGV[0]");
while(<F1>){
chomp;
## Split the line on whitespace into the @F array.
my @F=split(/\s+/);
## Save all lines in the %file1 hash.
## $F[0] is the contig name and $F[1] the value.
## The hash will store a list of all values
## associated with this contig.
push @{$file1{$F[0]}},$F[1];
}
close(F1);
## read file2, the second argument
open(F2,"$ARGV[1]");
while(<F2>){
## remove newlines
chomp;
## save the fields into array @F
my @F=split(/\s+/);
## Again, save all values associated with each
## contig into the %file2 hash.
push @{$file2{$F[0]}},$F[1];
}
close(F2);
## For each of the contigs in file1
foreach my $contig (keys(%file1)) {
## If this contig exists in file 2
if(defined $file2{$contig}){
## get the list of values for that contig
## in each of the two files
my @f2_vals=@{$file2{$contig}};
my @f1_vals=@{$file1{$contig}};
## For each of file1's values for this contig
val1:foreach my $val1 (@f1_vals) {
## For each of file2's value for this contig
foreach my $val2 (@f2_vals) {
## Skip to the next value from file1 unless
## this one falls within the desired range.
unless(($val1 < $val2-10) || ($val1 > $val2+10)){
next val1;
}
}
## We will only get here if none of the values
## fell within the desired range. If so, we should
## print the value from file1.
print "$contig $val1\n";
}
}
## If this contig is not in file2, print the
## lines from file1. This will print all lines
## from file1 whose contig was not in file2.
else {
print "$contig $_\n" for @{$file1{$contig}}
}
}
텍스트 파일(예 foo.pl
: )에 저장하고 실행 가능하게 만든 후( chmod a+x foo.pl
) 다음과 같이 실행합니다.
./foo.pl file1 file2
귀하의 예에서는 다음을 반환합니다.
$ foo.pl file1 file2
Contig2 68
Contig3 102
Contig7 79