11

The Situation

I am in the process of creating a simple template file that will aid in creating future scripts for doing various tasks via command line on *nix systems. As part of this, I might like to ask the user to input data which needs to validated against a regular expression that is supplied in the source code.

The Issue

Errors are begin generated when I attempt to run the Perl code via command line. I am attempting to pass a regular expression into the repeat subroutine and I'm not sure how to exactly do this. I am aware that I can execute a string using eval, however this is something that I would like to avoid due to convention.

The errors:

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.

The code:

#!/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");

What I have tried:

Based on these sources:


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

Any help is appreciated!

2
  • This &repeat(/foo|bar/i, "y"); is not passing a regex, this is passing the result of $_ =~ /foo|bar/i . Commented Dec 17, 2013 at 23:49
  • 2
    I would also note that if you allow the user to enter regexes, you're essentially saying "please type in code and I will execute it." qr/?{ system "rm -rf *" }/ is going to make for an unhappy day. Commented Dec 17, 2013 at 23:56

2 Answers 2

19

To create a regular expression for use later, we use qr//:

my $regexp = qr/^Perl$/;

This compiles the regular expression for use later. If there's a problem with your regular expression, you'll hear about it immediately. To use this pre-compiled regular expression you can use any of the following:

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

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

# Comparing against $_
/$regexp/;
Sign up to request clarification or add additional context in comments.

Comments

5

A bare regex literal like /.../ matches agains $_. To create an independent regex object, use qr// quotes:

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

(and please don't invoke subs like &sub unless you know when and why this is neccessary.)

2 Comments

When and why is it necessary?
@djthoms there is a good overview of the & in Perl by ikegami which mentions the cases (in short, &sub is only necessary when disabling a certain feature called “prototypes”, which you aren't even using).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.