如何重新定义 \s 以匹配下划线?

How to redefine \s to match underscores?

Perl (< v5.18) 正则表达式字符 class \s[\t\n\f\r ].

相同

现在,由于某些文件名使用下划线作为空格,我想知道是否可以重新定义 \s(本地)以匹配下划线和空格。

这仅仅是为了具有许多 [\s_] 的复杂正则表达式的可读性。我可以这样做吗?如果是这样,如何?

每当我认为某些事情在 Perl 中是不可能的,通常事实证明我错了。有时当我认为 Perl 中的某些东西非常困难时,我也错了。 @sln 将我指向 right track

我们暂时不要覆盖 \s,尽管您可以。为了你的程序的继承人希望 \s 表示特定的东西,让我们在正则表达式中定义序列 \_ 表示 "any whitespace character or the _ character" 。详细信息在上面的 link 中,但实现看起来像:

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{}}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.