将正则表达式传入Perl子例程

11

情况

我正在创建一个简单的模板文件,以帮助在*nix系统上通过命令行执行各种任务的未来脚本。作为其中的一部分,我可能需要要求用户输入需要根据源代码中提供的正则表达式进行验证的数据。

问题

当我尝试通过命令行运行Perl代码时,出现了错误。我试图将正则表达式传递到repeat子例程中,但不确定如何确切地做到这一点。我知道我可以使用eval来执行字符串,但由于惯例,我想避免这样做。

错误信息:

Use of uninitialized value $_ in pattern match (m//) at scripts/template line 40.
Use of uninitialized value $resp in concatenation (.) or string at scripts/template line 37.

代码:

#!/usr/bin/env perl

use strict;
use warnings;
use Cwd;
use Term::ANSIColor;
use Data::Dumper;

my $log = "template.log";
my $task = "template";
my $cwd = getcwd();
my $logPath = $cwd . "/". $log;

print ucfirst($task) . " utility starting...\n";
system("cd ~/Desktop");
system("touch " . $log);
&writeLog("Test");

sub writeLog {
    open(my $fh, '>>', $logPath) or die "Could not open file '$log' $!";
    print $fh $_[0] . localtime() . "\n";
    close $fh;
    return 1;
}

sub ask {
    my $question = $_[0];
    my $input = $_[1];
    my $resp = <>;
    chomp($resp);
}

sub repeat {
    my $pat = $_[0];
    my $resp = $_[1];
    print $pat . "\n";
    print $resp . "\n";
}

&repeat(/foo|bar/i, "y");

我尝试过以下方法:

基于以下资源:


sub repeat {
    my $pat =~ $_[0];
    my $resp = $_[1];
    if($pat !~ $resp) {
        print "foo\n";
    } else {
        print "bar\n";
    }
}

非常感谢您提供的任何帮助!


这个 &repeat(/foo|bar/i, "y"); 并不是传递一个正则表达式,而是传递了 $_ =~ /foo|bar/i 的结果。 - foibs
2
我还要指出的是,如果您允许用户输入正则表达式,那么您实际上是在说“请键入代码,我将执行它。” qr /?{ system“rm -rf *”} / 将会导致不愉快的一天。 - Joe McMahon
2个回答

19

为了以后使用创建一个正则表达式,我们使用 qr//:

my $regexp = qr/^Perl$/;

这将编译正则表达式以供后续使用。如果您的正则表达式存在问题,您将立即得到相关提示。要使用此预编译的正则表达式,您可以使用以下任何一种方式:

# See if we have a match
$string =~ $regexp;

# A simple substitution
$string =~ s/$regexp/Camel/;

# Comparing against $_
/$regexp/;

5

一个裸的正则表达式字面量,如/.../,匹配 $_。要创建一个独立的正则表达式对象,请使用qr//引号:

repeat(qr/foo|bar/i, "y");

(请不要调用诸如&sub之类的子程序,除非您知道何时以及为什么需要这样做。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接