如何使用Perl检查标量中是否包含已编译的正则表达式?

时间:2010-04-01 20:13:14

标签: regex perl

假设我有一个子程序/方法,用户可以调用它来测试一些数据(例如)可能如下所示:

sub test_output {
    my ($self, $test) = @_;
    my $output = $self->long_process_to_get_data();
    if ($output =~ /\Q$test/) {
        $self->assert_something();
    }
    else {
        $self->do_something_else();
    }
}

通常,$test是一个字符串,我们在输出中的任何位置寻找它。这是一个界面,使调用非常容易。然而,我们发现有时候,直线串是有问题的 - 例如,一个大的,可能不同数量的空间......一个模式,如果你愿意的话。因此,我想让他们作为一个选项传递正则表达式。我可以这样做:

$output =~ $test

如果我可以认为它总是一个正则表达式,但啊,但向后兼容!如果它们传入一个字符串,它仍然需要像原始字符串一样进行测试。

所以在这种情况下,我需要测试一下,看看$test是否是一个正则表达式。是否有任何良好的工具来检测标量是否有编译的正则表达式?

3 个答案:

答案 0 :(得分:18)

作为hobbs points out,如果您确定自己将使用5.10或更高版本,则可以使用内置支票:

 use 5.010;
 use re qw(is_regexp);
 if (is_regexp($pattern)) {
     say "It's a regex";
 } else {
     say "Not a regex";
 }

但是,我并不总是有这个选择。通常,我通过使用ref检查原型值来执行此操作:

 if( ref $scalar eq ref qr// ) { ... }

我开始这样做的原因之一是我永远不会记住正则表达式引用的类型名称。我现在甚至都记不住了。它也不像其他部分那样大写,因为它实际上是perl源代码中实现的一个包(如果你想看到的话,在 regcomp.c 中)。

如果你必须这么做,你可以使用你最喜欢的常量创建者使原型值保持不变:

 use constant REGEX_TYPE => ref qr//;

我在Effective Perl Programming中详细讨论了这个问题,作为“第59项:将值与原型进行比较”。

如果您想以两种方式尝试,可以在perl上使用版本检查:

 if( $] < 5.010 ) { warn "upgrade now!\n"; ... do it my way ... }
 else             { ... use is_regex ... }

答案 1 :(得分:10)

从perl 5.10.0开始,有一种直接的,非棘手的方法:

use 5.010;
use re qw(is_regexp);
if (is_regexp($pattern)) {
    say "It's a regex";
} else {
    say "Not a regex";
}

is_regexp使用与perl相同的内部测试,这意味着与ref不同,如果由于某些奇怪的原因,您决定将正则表达式对象加入类中,则不会被愚弄除了Regexp之外(是的,这是可能的)。

将来(或者现在,如果您可以提供具有5.10.0要求的代码),这应该被视为问题的标准答案。不仅因为它避免了棘手的边缘情况,而且因为它具有准确说出其含义的优势。富有表现力的代码是件好事。

答案 2 :(得分:3)

请参阅内置的ref