Точное совпадение строк в Perl с использованием quotemeta () - PullRequest
1 голос
/ 31 декабря 2011

Я пытаюсь использовать quotemeta в Perl.Ниже приведен код со строкой и шаблоном, который я пытаюсь найти:

open FH, "<query.txt";

@foo = <FH>;
my $bar = "A lymph node Elspar (Merck & Co. Inc) Thyrogen (Genzyme Inc) metastasis 
PEG-Intron  (Schering Corp) specimen from a human testicular embryonal carcinoma with
 elements of a choriocarcinoma Secremax, SecreFlo Secremax, SecreFlo (Repligen Corp)";

foreach my $word(@foo) {
chomp $word;
if ($bar =~ /\b\Q$word\E\b/i)
{
print "$word\n";
}
}

Скажем, query.txt - это файл, который содержит следующие термины, которые я пытаюсь найтинайдите в строке:

Elspar (Merck & Co. Inc)
Thyrogen (Genzyme Inc)
PEG-Intron  (Schering Corp)
Secremax, SecreFlo
Secremax, SecreFlo (Repligen Corp)

Кажется, мой код не работает, я не понимаю, что происходит не так.

ОБНОВЛЕНИЕ:

If $bar = "A lymph node Elspar (Merck & Co. Inc) Thyrogen (Genzyme Inc) metastasis 
PEG-Intron  (Schering Corp) specimen from a human testicular embryonal carcinoma with
 elements of a choriocarcinoma Secremax, SecreFlo Secremax, SecreFlo (Repligen Corp)
specimen from a human testicular embryonal carcinoma with elements of a choriocarcinoma
was successfully  xenotransplanted into nude mice and maintained until the tenth animal
passage. Electron microscopy of the tumors in nude mice revealed details Secremax,
SecreFlo consistent with their epithelial origin.";

И query.txt также содержит следующие термины:

 pa
 the
 scopy
 ealed

Ответы [ 4 ]

6 голосов
/ 31 декабря 2011

Проблема в \b, который вы окружили поиском.\b соответствует только между символом \w и символом, отличным от \w (или в начале или в конце строки).Поскольку ) не является символом слова и не является пробелом, \)\b не соответствует ") ".

Решение зависит от того, что именно вы пытаетесь сделать.Может быть, вы хотели

$bar =~ /(?<!\w)\Q$word\E(?!\w)/i

Что говорит о том, что совпадение не должно касаться символа \w с обеих сторон.

Ответ на обновление:

За исключением the, ваши строки запроса не являются словами.Если вы хотите сопоставить частичные слова, то вы вообще не хотите \b.Звучит так, будто вы просто имеете в виду:

$bar =~ /\Q$word\E/i

Что означает "просто найди $word, и мне все равно, что к нему прикасается".

4 голосов
/ 31 декабря 2011

Я добавил use strict; и use warnings;, вставил my перед @foo и оператор печати в цикле:

foreach my $word (@foo)
{
    chomp $word;
    print "Checking $word:\n";
    if ($bar =~ /\b\Q$word\E\b/i)
    {
        print "Match $word\n";
    }
}

Затем я получил этот вывод из Perl 5.12.3 наMacOS X 10.7.2 (Lion):

Checking Elspar (Merck & Co. Inc):
Checking Thyrogen (Genzyme Inc):
Checking PEG-Intron  (Schering Corp):
Checking Secremax, SecreFlo:
Match Secremax, SecreFlo
Checking Secremax, SecreFlo (Repligen Corp):

Итак, когда $word не содержит метасимволов регулярных выражений, сопоставление с образцом сработало для меня.Однако это не так просто, как «нотация \Q..\E не работает»;Я изменил файл query.txt следующим образом:

Elspar .Merck . Co. Inc.
Thyrogen .Genzyme Inc.
PEG-Intron  .Schering Corp.
Secremax, SecreFlo
Secremax, SecreFlo .Repligen Corp.

и получил тот же результат, что и раньше.Это оставляет обозначение \b подозрительным;некоторые из ваших строк не соответствуют границам слов.Если я уберу обе отметки \b из регулярного выражения, то получу:

Checking Elspar (Merck & Co. Inc):
Match Elspar (Merck & Co. Inc)
Checking Thyrogen (Genzyme Inc):
Match Thyrogen (Genzyme Inc)
Checking PEG-Intron  (Schering Corp):
Match PEG-Intron  (Schering Corp)
Checking Secremax, SecreFlo:
Match Secremax, SecreFlo
Checking Secremax, SecreFlo (Repligen Corp):
Match Secremax, SecreFlo (Repligen Corp)

Вы можете оставить первое \b;это дает тот же результат.Закрывающие круглые скобки создают проблемы, потому что после пробела (как в тексте) они не обозначают границу между словом и несловом.


Ответ на измененный вопрос

Этот код работает как требуется.В основном, это выглядит, чтобы увидеть, как построить запрос:

use strict;
use warnings;

open FH, "<query.txt";

my @foo = <FH>;
#my $bar = "A lymph node Elspar (Merck & Co. Inc) Thyrogen (Genzyme Inc) metastasis PEG-Intron  (Schering Corp) specimen from a human testicular embryonal carcinoma with elements of a choriocarcinoma Secremax, SecreFlo Secremax, SecreFlo (Repligen Corp)";

my $bar =  "A lymph node Elspar (Merck & Co. Inc) Thyrogen (Genzyme Inc) metastasis PEG-Intron  (Schering Corp) specimen from a human testicular embryonal carcinoma with elements of a choriocarcinoma Secremax, SecreFlo Secremax, SecreFlo (Repligen Corp) specimen from a human testicular embryonal carcinoma with elements of a choriocarcinoma was successfully  xenotransplanted into nude mice and maintained until the tenth animal passage. Electron microscopy of the tumors in nude mice revealed details Secremax, SecreFlo consistent with their epithelial origin.";

foreach my $word (@foo)
{
    chomp $word;
    print "Checking $word:\n";
    my ($pfx, $sfx) = ('', '');
    $pfx = '\b' if ($word =~ /^\w/);
    $sfx = '\b' if ($word =~ /\w$/);
    if ($bar =~ /$pfx\Q$word\E$sfx/i)
    {
        print "Match $word\n";
    }
}

Пример вывода:

Checking Elspar (Merck & Co. Inc):
Match Elspar (Merck & Co. Inc)
Checking Thyrogen (Genzyme Inc):
Match Thyrogen (Genzyme Inc)
Checking PEG-Intron  (Schering Corp):
Match PEG-Intron  (Schering Corp)
Checking Secremax, SecreFlo:
Match Secremax, SecreFlo
Checking Secremax, SecreFlo (Repligen Corp):
Match Secremax, SecreFlo (Repligen Corp)
Checking pa:
Checking the:
Match the
Checking scopy:
Checking ealed:

Это выглядит правильно для меня.Работает ли это во всех возможных сценариях, открыто для обсуждения.Возможно, вам придется беспокоиться о том, соответствует ли (Secremax, Secreflow (Repligen Corp)) шаблон «Repligen» в нем, а если нет, вам нужно дать более строгое определение того, что составляет соответствие.

4 голосов
/ 31 декабря 2011

\b соответствует только границе слова, но некоторые из ваших шаблонов заканчиваются круглыми скобками, которые не являются границей слова.Вместо этого используйте регулярное выражение /(?<!\w)\Q$word\E(?!\w)/i, которое гарантирует, что вашему совпадению не предшествует и не следует слово.

1 голос
/ 31 декабря 2011

используйте quotemeta так:

open FH, "<query.txt";

@foo = <FH>;
my $bar = "A lymph node Elspar (Merck & Co. Inc) Thyrogen (Genzyme Inc) metastasis 
PEG-Intron  (Schering Corp) specimen from a human testicular embryonal carcinoma with
 elements of a choriocarcinoma Secremax, SecreFlo Secremax, SecreFlo (Repligen Corp)";

foreach my $word(@foo) {
    chomp $word;

    my $quoted_word = quotemeta($word);

    if ($bar =~ m/$quoted_word/i){
        print "$word\n";
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...