如何使perl正则表达式选项有条件

Sim*_*ett 1 regex perl

不要问为什么,但......

我有一个正则表达式,如果在Windows上运行需要不区分大小写但在*nix上运行时区分大小写.

这是我目前正在做的事情的一个示例片段.

sub relative_path 
{
    my ($root, $path) = @_;

    if ($os eq "windows")
    {
        # case insensitive with regex option 'i'
        if ($path !~ /^\Q$root\E[\\\/](.*)$/i)
        {
            print "\tFAIL:$root not in $path\n";
        }
        else
        {
            return $1;
        }
    }
    else
    {
        # case sensitive
        if ($path !~ /^\Q$root\E[\\\/](.*)$/)
        {
            print "\tFAIL:$root not in $path\n";
        }
        else
        {
            return $1;
        }
    }
    return "";
}
Run Code Online (Sandbox Code Playgroud)

哎呀!重复会伤害我的强迫症,但我的perl-fu很弱.不知何故,我想使用正则表达式选项'我'的条件不敏感条件,但我现在不怎么样?

Sin*_*nür 9

您可以使用扩展构造来指定选项.例如:

#!/usr/bin/env perl

use warnings; use strict;

my $s = 'S';

print check($s, 'i'), "\n";
print check($s, '-i'), "\n";

sub check {
    my ($s, $opt) = @_;
    return "Matched" if $s =~ /(?$opt)^s\z/;
    return "Did not match";
}
Run Code Online (Sandbox Code Playgroud)

perldoc perlre.

  • 由于DRY而+1.我想指出`(?p`在perl 5.8.9上不起作用,并且在该版本的`perlre`文档中没有提到它.它似乎在没有5.8.9的'p`的情况下工作,但我的猜测是在5.10中增加了"?p" (2认同)

Pla*_*ure 5

您可以使用qr运算符创建模式并将其存储在标量中:

sub relative_path 
{
    my ($root, $path) = @_;

    my $pattern = ($os eq "windows") ? qr/^\Q$root\E[\\\/](.*)$/i : qr/^\Q$root\E[\\\/](.*)$/;

    if ($path !~ $pattern)
    {
        print "\tFAIL:$root not in $path\n";
    }
    else
    {
        return $1;
    }
}
Run Code Online (Sandbox Code Playgroud)

这可能不是100%完美,但希望你应该明白这一点.

请务必查看perlop中的"引用和引用类操作符"部分.


编辑:好的,这是一个干燥的解决方案,因为人们抱怨它.

sub relative_path 
{
    my ($root, $path) = @_;

    my $base_pattern = qr/^\Q$root\E[\\\/](.*)$/;
    my $pattern = ($os eq "windows") ? qr/$base_pattern/i : $base_pattern;

    if ($path !~ $pattern)
    {
        print "\tFAIL:$root not in $path\n";
    }
    else
    {
        return $1;
    }
}
Run Code Online (Sandbox Code Playgroud)