Мне нужно совместить два файла и печатать только те строки, которые после определенного символа не выполняются только элементами из одного из файлов.
Например, у меня есть два файла, которые выглядят следующим образом:
1A00.pdb_HEM_COA
1A01.pdb_HEM
1A05.pdb_IPM
1A0F.pdb_GTS_4CA
1A0G.pdb_PMP
1A0I.pdb_2CP
и это:
COA
2CP
3CP
3HC
4CA
4CO
Я хочу их сопоставить, и если окажется, что сначала _ следует только элементы из второго файла, тогда не печатайте их (пример 1A0I.pdb_2CP). Если в других строках кажется, что _ следует за некоторым другим элементом, но также элементом из второго файла, а затем просто удаляет этот элемент, который является общим в обоих файлах, но печатает строку (например, 1A00.pdb_HEM_COA, а печатная строка должна быть как 1A00.pdb_HEM).
Кто-нибудь знает, как это сделать?
Вы можете создать хеш perl из строк второго файла
#!/usr/bin/perl -w
use strict;
BEGIN{ $/ = $\ = "\n"; }
my $stringsfile = shift @ARGV;
open(my $fh, '<:encoding(UTF-8)', $stringsfile)
or die "Could not open file '$stringsfile' $!";
my %h;
while (defined($_ = <$fh>)) {
chomp $_;
$h{$_} = 1;
}
, а затем разделить строки первого (и последующих) файлов на дефисные поля, grep для этих полей которые не находятся в хеше, и присоедините их все вместе и напечатайте, если grep возвращает что-либо:
while (defined($_ = <ARGV>)) {
chomp $_;
my ($x, @F) = split(/_/, $_, 0);
my @y = grep({not $h{$_};} @F);
print join('_', $x, @y) if @y;
}
Использование:
$ ./foo.pl file2 file1
1A00.pdb_HEM
1A01.pdb_HEM
1A05.pdb_IPM
1A0F.pdb_GTS
1A0G.pdb_PMP
Примечание: если потенциальные совпадения находятся в конце, то с помощью awk существует гораздо более простой подход:
awk '
BEGIN{OFS=FS="_"}
NR==FNR {a[$0]++; next}
{while ($NF in a) NF--}
NF>1 {print}
' file2 file1
. Для выборочных данных в вашем вопросе оба подхода создают одинаковый вывод.
Вы можете создать хеш perl из строк второго файла
#!/usr/bin/perl -w
use strict;
BEGIN{ $/ = $\ = "\n"; }
my $stringsfile = shift @ARGV;
open(my $fh, '<:encoding(UTF-8)', $stringsfile)
or die "Could not open file '$stringsfile' $!";
my %h;
while (defined($_ = <$fh>)) {
chomp $_;
$h{$_} = 1;
}
, а затем разделить строки первого (и последующих) файлов на дефисные поля, grep для этих полей которые не находятся в хеше, и присоедините их все вместе и напечатайте, если grep возвращает что-либо:
while (defined($_ = <ARGV>)) {
chomp $_;
my ($x, @F) = split(/_/, $_, 0);
my @y = grep({not $h{$_};} @F);
print join('_', $x, @y) if @y;
}
Использование:
$ ./foo.pl file2 file1
1A00.pdb_HEM
1A01.pdb_HEM
1A05.pdb_IPM
1A0F.pdb_GTS
1A0G.pdb_PMP
Примечание: если потенциальные совпадения находятся в конце, то с помощью awk существует гораздо более простой подход:
awk '
BEGIN{OFS=FS="_"}
NR==FNR {a[$0]++; next}
{while ($NF in a) NF--}
NF>1 {print}
' file2 file1
. Для выборочных данных в вашем вопросе оба подхода создают одинаковый вывод.
Вы можете создать хеш perl из строк второго файла
#!/usr/bin/perl -w
use strict;
BEGIN{ $/ = $\ = "\n"; }
my $stringsfile = shift @ARGV;
open(my $fh, '<:encoding(UTF-8)', $stringsfile)
or die "Could not open file '$stringsfile' $!";
my %h;
while (defined($_ = <$fh>)) {
chomp $_;
$h{$_} = 1;
}
, а затем разделить строки первого (и последующих) файлов на дефисные поля, grep для этих полей которые не находятся в хеше, и присоедините их все вместе и напечатайте, если grep возвращает что-либо:
while (defined($_ = <ARGV>)) {
chomp $_;
my ($x, @F) = split(/_/, $_, 0);
my @y = grep({not $h{$_};} @F);
print join('_', $x, @y) if @y;
}
Использование:
$ ./foo.pl file2 file1
1A00.pdb_HEM
1A01.pdb_HEM
1A05.pdb_IPM
1A0F.pdb_GTS
1A0G.pdb_PMP
Примечание: если потенциальные совпадения находятся в конце, то с помощью awk существует гораздо более простой подход:
awk '
BEGIN{OFS=FS="_"}
NR==FNR {a[$0]++; next}
{while ($NF in a) NF--}
NF>1 {print}
' file2 file1
. Для выборочных данных в вашем вопросе оба подхода создают одинаковый вывод.