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

Rob*_*t P 4 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

$output =~ $test
Run Code Online (Sandbox Code Playgroud)

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

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

bri*_*foy 18

正如霍布斯指出的那样,如果您确定自己将使用5.10或更高版本,则可以使用内置支票:

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

但是,我并不总是有这个选择.一般来说,我通过使用ref检查原型值来做到这一点:

 if( ref $scalar eq ref qr// ) { ... }
Run Code Online (Sandbox Code Playgroud)

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

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

 use constant REGEX_TYPE => ref qr//;
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 我讨厌魔术常数和硬编码的字符串,我尽力摆脱它们.它们通常是糟糕的编程习惯. (3认同)
  • 你不必问我所有这些问题.亲自尝试一下.:) (3认同)
  • 在5.12.0中,正则表达式对象实际上变得更加"核心",因为它们现在引用了REGEXP类型的标量,而不是引用带有魔法的标量.但是,这对于用户代码是完全不可见的,除非你设法绕过重载的字符串化,在这种情况下你会注意到正则表达式现在打印为`Regexp = REGEXP(0x1234567)`而不是`Regexp = SCALAR(0x1234567)`: ) (3认同)

hob*_*bbs 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";
}
Run Code Online (Sandbox Code Playgroud)

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

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