Как я могу искать фиксированный и нечувствительный к регистру строковый шаблон в массиве в Perl?

Я хочу создать perl-скрипт для получения списка значений (ключей в хэше) и поиска его в массиве. Мне нужно найти фиксированный шаблон, но он может быть нечувствительным к регистру. Это мой код:

foreach my $element ( keys %data ) {
    # this line search the exact pattern, but it isn't case insensitive
    if ( first { $element eq $_ } @database_lines ) {
        $counter += 1;
        print "$element\n";
    } else {
        next;
    }
}

Некоторые идеи? Заранее спасибо.


person Cristian Velandia    schedule 24.08.2014    source источник


Ответы (3)


Я бы, вероятно, создал хеш содержимого @database_lines в нижнем регистре, а затем искал бы его:

my %db_lines;
$db_lines{lc $_} = 1 for @database_lines;

foreach my $element (keys %data) {
    if ($db_lines{lc $element}) {
        $counter++;
        print "$element\n";
    }
}

Если ваш Perl достаточно новый, вы можете использовать fc вместо lc, чтобы обеспечить более точное сопоставление без учета регистра.

person Jim Davis    schedule 24.08.2014
comment
Первые две строки как одна строка: my %db_lines = map { lc($_) => 1 } @database_lines;. - person ikegami; 25.08.2014

Это проверит использование условия «содержит»:

@f = grep /\Q$element\E/i, @lines;
print $f[0];

Если вам нужно точное совпадение, используйте:

@f = grep /^\Q$element\E\z/i, @lines;
print $f[0];
person Oleg Gryb    schedule 25.08.2014
comment
Итак, вы предлагаете изменить first { $element eq $_ } на first { /^\Q$element\E$/i } - person ikegami; 25.08.2014
comment
@ikegami - Пожалуйста, объясните необходимость цитирования. Если вы не можете, верните все к исходному ответу (удаление скобок в порядке). Вот пример, который может помочь: $e='/';@f = grep /$e/i, ('/');print $f[0]; - person Oleg Gryb; 26.08.2014
comment
$element = 'a*b'; $element =~ /$element/i ложно, поэтому /$element/i не проверяет, содержится ли $element в $_. $element = 'a*b'; $element =~ /^$element$/i ложно, поэтому /^$element$/i не проверяет, равно ли $_ $element. Итак, мои исправления. - person ikegami; 26.08.2014
comment
Вы говорите, что $element =~ /$element/i ложно, но приведенный ниже код выводит '1': perl -e '$element = a*b; print ($element =~ /$element/i);' - person Oleg Gryb; 26.08.2014
comment
Извините, неудачный пример. Используйте 1_ - person ikegami; 26.08.2014
comment
Интересно. Я до сих пор не понимаю, почему, но спасибо за этот прекрасный пример. Сохраню цитату в ответе :) - person Oleg Gryb; 26.08.2014
comment
/ab*c/ соответствует строкам, которые содержат a, за которым следует 0 или более b, за которым следует c. ab*c не содержит такой последовательности. // /\Qab*c/ или /ab\*c/ соответствует строкам, которые содержат a, за которым следует b, за которым следует *, за которым следует c. ab*c содержит такую ​​последовательность. - person ikegami; 26.08.2014
comment
Хорошо понял. Я не понимал, что внутренняя переменная интерпретируется как регулярное выражение. Хотя я бы воспринял это буквально. - person Oleg Gryb; 26.08.2014
comment
Если бы он автоматически цитировался, вы не могли бы построить шаблон динамически. например m{http://$host_pat...} - person ikegami; 26.08.2014

Я бы порекомендовал выполнить это задание таким образом

use v5.16;
my $count = do {
    my %hash;
    @hash{map fc, @database_lines} = ();
    grep exists $hash{fc($_)}, keys %data;
};

Преимущество в том, что этот код O(M+N) вместо O(M*N) вашего исходного подхода.

person Hynek -Pichi- Vychodil    schedule 16.03.2015