Как переопределить 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.