#regex #perl #string-matching
#регулярное выражение #perl #сопоставление строк
Вопрос:
Я использую a regex
, но получаю несколько странных, неожиданных «совпадений». «Имена» отправляются в подпрограмму для сравнения с вызываемым массивом @ASlist
, который содержит несколько строк. Первый элемент каждой строки также является именем, за которым следует от 0 до нескольких синонимов. Цель состоит в том, чтобы сопоставить входящее «имя» с любой строкой, в @ASlist
которой есть соответствующая ячейка.
Пример ввода, из которого $names
извлекается для сравнения с @ASlist
:
13 1 13 chr7 7 70606019 74345818 Otud7a Klf13 E030018B13Rik Trpm1 Mir211 Mtmr10 Fan1 Mphosph10 Mcee Apba2 Fam189a1 Ndnl2 Tjp1 Tarsl2 Tm2d3 1810008I18Rik Pcsk6 Snrpa1 H47 Chsy1 Lrrk1 Aldh1a3 Asb7 Lins Lass3 Adamts17
Примеры строк из @asList:
HSPA5 BIP FLJ26106 GRP78 MIF2
NDUFA5 B13 CI-13KD-B DKFZp781K1356 FLJ12147 NUFM UQOR13
ACAN AGC1 AGCAN CSPG1 CSPGCP MSK16 SEDK
Код:
my ($name) = @_; ## this comes in from another loop elsewhere in code I did not include
chomp $name;
my @collectmatches = (); ## container to collect matches
foreach my $ASline ( @ASlist ){
my @synonyms = split("t", $ASline );
for ( my $i = 0; $i < scalar @synonyms; $i ){
chomp $synonyms[ $i ];
#print "COMPARE $name TO $synonyms[ $i ]n";
if ( $name =~m/$synonyms[$i]/ ){
print "tname $name from block matchesnt$synonyms[0]ntvia $synonyms[$i] from AS listn";
push ( @collectmatches, $synonyms[0], $synonyms[$i] );
}
else {
# print "$name does not match $synonyms[$i]n";
}
}
}
Скрипт работает, но также сообщает о странных совпадениях. Например, когда $name
«E030018B13Rik» соответствует «NDUFA5», когда он встречается в @ASlist
. Эти два не должны совпадать.
Если я изменю регулярное выражение с ~m/$synonyms[$i]/
на ~m/^$synonyms[$i]$/
, «странные» совпадения исчезнут, НО сценарий пропустит подавляющее большинство совпадений.
Комментарии:
1. Ваши входные данные выглядят как данные фиксированной ширины. Так ли это? Если это так, регулярное выражение может даже не быть оптимальным инструментом для распаковки данных.
Ответ №1:
NDUFA5
Запись содержит B13
в качестве шаблона, который будет соответствовать E030018<B13>Rik
.
Если вы хотите быть более буквальным, добавьте граничные условия в свое регулярное выражение /b...b/
. Также, вероятно, следует избегать использования специальных символов регулярного выражения quotemeta
.
if ( $name =~ m/bQ$synonyms[$i]Eb/ ) {
Или, если вы хотите проверить прямое равенство, просто используйте eq
if ( $name eq $synonyms[$i] ) {
Комментарии:
1. Я не понимаю, как именно эти два на самом деле совпадают?
2. Потому
B13
что находится внутри строкиE030018B13Rik
. Если вы не хотите, чтобы это выполнялось подобным образом, вам нужно добавить граничные условия к регулярному выражению.
Ответ №2:
Другой, более простой способ проверки на равенство строк — использовать хэш.
Вы не показываете никаких реальных тестовых данных, но эта короткая программа Perl создает хэш из вашего массива @ASlist
строк совпадающих строк. После этого большая часть работы выполнена.
Последующий for
цикл проверяет E030018B13Rik
, является ли он одним из ключей нового %ASlist
, и печатает соответствующее сообщение
use strict;
use warnings;
my @ASlist = (
'HSPA5 BIP FLJ26106 GRP78 MIF2',
'NDUFA5 B13 CI-13KD-B DKFZp781K1356 FLJ12147 NUFM UQOR13',
'ACAN AGC1 AGCAN CSPG1 CSPGCP MSK16 SEDK',
);
my %ASlist = map { $_ => 1 } map /S /g, @ASlist;
for (qw/ E030018B13Rik /) {
printf "%s %sn", $_, $ASlist{$_} ? 'matches' : 'doesn't match';
}
вывод
E030018B13Rik doesn't match
Ответ №3:
Поскольку вам нужно сравнить только две строки, вы можете просто использовать eq:
if ( $name eq $synonyms[$i] ){
Ответ №4:
Вы используете B13
в качестве регулярного выражения. Поскольку ни один из символов не имеет специального значения, любая строка, содержащая подстроку B13
, соответствует выражению.
E030018B13Rik
^^^
Если вы хотите, чтобы выражение соответствовало всей строке, используйте привязки:
if ($name =~m/^$synonyms[$i]$/) {
Или используйте index
или eq
для обнаружения подстрок (или идентичных строк соответственно), поскольку ваш ввод, похоже, не использует какие-либо функции регулярных выражений.
Комментарии:
1. Я теряю много потенциальных совпадений, используя эти точные привязки, но я вижу, что могу изменить регулярное выражение, чтобы оно не учитывало регистр…