Передать регулярное выражение в подпрограмму perl

Ситуация

Я создаю простой файл шаблонов, который поможет создавать будущие скрипты для выполнения различных задач через командную строку на системах * 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";
    }
}

Любая помощь приветствуется!

Ответ 1

Чтобы создать регулярное выражение для использования позже, мы используем qr//:

my $regexp = qr/^Perl$/;

Скомпилирует регулярное выражение для использования позже. Если возникнет проблема с вашим регулярным выражением, вы сразу узнаете об этом. Чтобы использовать это предварительно скомпилированное регулярное выражение, вы можете использовать любое из следующих значений:

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

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

# Comparing against $_
/$regexp/;

Ответ 2

Голый литерал регулярного выражения, подобный /.../, снова соответствует $_. Чтобы создать независимый объект регулярного выражения, используйте qr// кавычки:

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

(и, пожалуйста, не вызывайте subs вроде &sub, если вы не знаете, когда и почему это необходимо.)