Как переопределить s, чтобы соответствовать подчеркиваниям?
Perl (s для пробельных символов совпадает с [tnfr ]
.
Теперь, поскольку некоторые имена файлов используют подчеркивание в качестве пробелов, мне было интересно, можно ли переопределить s
(локально), чтобы соответствовать подчеркиванию в дополнение к пробелам.
Это было бы просто ради удобства чтения в противном случае запутанных регулярных выражений, имеющих много [s_]
. Могу я это сделать? Если да, то как?
1 ответ:
Всякий раз, когда я думаю, что что-то невозможно в Perl, обычно оказывается, что я ошибаюсь. И иногда, когда я думаю, что что-то очень трудно в Perl, я тоже ошибаюсь. @sln указал мне на правильный путь
Давайте пока не будем переопределять
\s
, хотя могли бы. Для наследников вашей программы, которые ожидают, что\s
будет означать что-то конкретное, вместо этого давайте определим последовательность\_
как "любой символ пробела или символ_
" внутри a регулярное выражение. Подробности приведены в ссылке выше, но реализация выглядит следующим образом:package myspace; # redefine \_ to mean [\s_] use overload; my %rules = ('\\' => '\\\\', '_' => qr/[\t\n\x{0B}\f\r _]/ ); sub import { die if @_ > 1; overload::constant 'qr' => sub { my $re = shift; $re =~ s{\\(\\|_)}{$rules{$1}}gse; return $re; }; } 1;
Теперь в вашем сценарии скажите
use myspace;
А теперь
\_
в регулярном выражении означает[\s_]
.Демо:
use myspace; while (<DATA>) { chomp; if ($_ =~ /aaa\s.*txt/) { # match whitespace print "match[1]: $_\n"; } if ($_ =~ /aaa\_.*txt/) { # match [\s_] print "match[2]: $_\n"; } if ($_ =~ /\\_/) { # match literal '\_' print "match[3]: $_\n"; } } __DATA__ aaabbb.txt aaa\_ccc.txt cccaaa bbb.txt aaa_bbb.txt
Вывод:
Третий случай-продемонстрировать, чтоmatch[3]: aaa\_ccc.txt match[1]: cccaaa bbb.txt match[2]: cccaaa bbb.txt match[2]: aaa_bbb.txt
\\_
в регулярном выражении будет соответствовать литералу\_
, Как\\s
будет соответствовать литералу\s
.