Как переопределить, чтобы соответствовать подчеркиваниям?
Perl ([\t\n\f\r ]
,
Теперь, так как некоторые имена файлов используют подчеркивание в качестве пробелов, мне было интересно, можно ли переопределить \s
(локально), чтобы соответствовать подчеркиваниям в дополнение к пробелам.
Это было бы просто ради удобочитаемости извилистых регулярных выражений, имеющих много [\s_]
, Я могу это сделать? Если так, то как?
1 ответ
Всякий раз, когда я думаю, что в Perl что-то невозможно, обычно оказывается, что я неправ. И иногда, когда я думаю, что что-то очень сложно в Perl, я тоже ошибаюсь. @sln указал мне правильный путь
Не будем переопределять \s
только пока, хотя вы могли бы. Ради наследников вашей программы, которые ожидают \s
что-то конкретное, вместо этого давайте определим последовательность \_
означать "любой символ пробела или _
символ "внутри регулярного выражения. Подробности в ссылке выше, но реализация выглядит следующим образом:
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
,