Избавьтесь от параметра $caseSensitive
, так как во многих случаях он будет бесполезен. Вместо этого пользователи этой функции могут закодировать необходимую информацию непосредственно в регулярном выражении $validationRe
.
Когда вы создаете объект регулярного выражения, такой как qr/foo/
, шаблон в этот момент компилируется в инструкции для механизма регулярных выражений. Если вы преобразуете объект регулярного выражения в строку, вы получите строку, которая при интерполяции обратно в регулярное выражение будет иметь точно такое же поведение, как и исходный объект регулярного выражения. Самое главное, это означает, что все флаги, предоставленные или опущенные в литерале объекта регулярного выражения, будут сохранены и не могут быть переопределены! Это сделано специально, чтобы объект регулярного выражения продолжал вести себя одинаково независимо от того, в каком контексте он используется.
Это немного сухо, так что давайте использовать пример. Вот функция match
, которая пытается применить пару похожих регулярных выражений к списку строк. Какой из них будет соответствовать?
use strict;
use warnings;
use feature 'say';
# This sub takes a string to match on, a regex, and a case insensitive marker.
# The regex will be recompiled to anchor at the start and end of the string.
sub match {
my ($str, $re, $i) = @_;
return $str =~ /\A$re\z/i if $i;
return $str =~ /\A$re\z/;
}
my @words = qw/foo FOO foO/;
my $real_regex = qr/foo/;
my $fake_regex = 'foo';
for my $re ($fake_regex, $real_regex) {
for my $i (0, 1) {
for my $word (@words) {
my $match = 0+ match($word, $re, $i);
my $output = qq("$word" =~ /$re/);
$output .= "i" if $i;
say "$output\t-->" . uc($match ? "match" : "fail");
}
}
}
Выход:
"foo" =~ /foo/ -->MATCH
"FOO" =~ /foo/ -->FAIL
"foO" =~ /foo/ -->FAIL
"foo" =~ /foo/i -->MATCH
"FOO" =~ /foo/i -->MATCH
"foO" =~ /foo/i -->MATCH
"foo" =~ /(?^:foo)/ -->MATCH
"FOO" =~ /(?^:foo)/ -->FAIL
"foO" =~ /(?^:foo)/ -->FAIL
"foo" =~ /(?^:foo)/i -->MATCH
"FOO" =~ /(?^:foo)/i -->FAIL
"foO" =~ /(?^:foo)/i -->FAIL
Во-первых, мы должны заметить, что строковое представление объектов регулярных выражений имеет эту странную форму (?^:...)
. В группе без захвата (?: ... )
модификаторы шаблона внутри группы могут быть добавлены или удалены между вопросительным знаком и двоеточием, а ^
указывает набор флагов по умолчанию.
Теперь, когда мы смотрим на фальшивое регулярное выражение, которое на самом деле является просто интерполируемой строкой, мы видим, что добавление флага /i
имеет ожидаемое значение. Но когда мы используем настоящий объект регулярного выражения, это ничего не меняет: внешний /i
не может переопределить флаги (?^: ... )
.
Вероятно, лучше всего предположить, что все регулярные выражения уже являются объектами регулярных выражений и не должны вмешиваться. Если вы загружаете шаблоны регулярных выражений из файла, вы должны потребовать, чтобы регулярные выражения использовали синтаксис (?: ... )
для применения флагов (например, (?^i:foo)
как эквивалент qr/foo/i
). Например. загрузка одного регулярного выражения на строку из дескриптора файла может выглядеть так:
my @regexes;
while (<$fh>) {
chomp;
push @regexes, qr/$_/; # will die here on regex syntax errors
}
person
amon
schedule
21.12.2014