Reputation: 792
there is something in Perl I don't know how to code, can I request your help please.
basically, I'm trying to use a configuration file with an array (or a hash or anything of that sort) containing "exceptions" that I want to use in a "next if" of a loop of the main program.
exemple :
my program looks like that :
while(<>) {
next if /regex1/;
next if /regex2/;
next if /regexN/;
}
and I want to be able to put these "next if" from a config file, like :
my %conf = do './config_file.conf';
while(<>) {
# put code here to add all 'next ifs';
}
config file example :
exceptions => [
'regex1',
'regex2',
'regexN',
],
how can I do this easily in my code ? (where the comment is, that is, adding all "next if" from an array
thanks ! regards,
Upvotes: 1
Views: 90
Reputation: 53498
In addition to the existing answers - I'd probably expand it to compile up a regex from my input:
#!/usr/bin/env perl
use strict;
use warnings;
my %conf = ( exceptions => [ 'regex1', 'regex2', 'regexN', ], );
my $match = join ( "|", @{$conf{exceptions}} );
$match = qr/\b$match\b/;
print "Using regex of: ",$match,"\n";
while ( <DATA> ) {
next if /$match/;
print;
}
__DATA__
regex0
regex1
regex2
regexA
regexB
regexN
This has an advantage over grep
in particular, that grep will iterate the whole list of regex, even if it hits a match early on. That won't matter noticeably if you've a small number of patterns though.
For bonus points, you may want to sort by likelihood of 'hit', so a match is located earlier on. By default, sorting by length might do it.
(And note - I use \b
word boundary anchors, which may not be what you want to do, given you are using regex as input)
Upvotes: 1
Reputation: 54373
You can use a another loop to iterate over all your patterns inside of your while
. If you assign a label to your while
loop you can next
that directly.
my %conf = ( exceptions => [ 'regex1', 'regex2', 'regexN', ], );
OUTER: while (<DATA>) {
foreach my $re (@{ $conf{exceptions} }) {
next OUTER if m/$re/;
}
print;
}
__DATA__
regex0
regex1
regex2
regexA
regexB
regexN
This will output
regex0
regexA
regexB
Note that the do './config_file.conf'
is very safe. You should use a module to read a config file format instead. That will make your code more portable and make sure no code you might not control gets executed. For example, you could use JSON, or Config::Simple.
Upvotes: -1
Reputation: 386331
Don't compile the patterns over and over again as simbabque and olivierg have recommended!
my %conf = ( exceptions => [ 'regex1', 'regex2', 'regexN', ], );
my $exceptions_re = join '|', @{ $conf{exceptions} };
$exceptions_re = qr/$exceptions_re/;
while (<DATA>) {
next if /$re/;
print;
}
If what you claim are regex patterns are actually strings to match literally, change
my $exceptions_re = join '|', @{ $conf{exceptions} };
to
my $exceptions_re = join '|', map quotemeta, @{ $conf{exceptions} };
Upvotes: 4
Reputation: 792
mmh it seems working with :
next if grep /$_/, @{$conf{exceptions}};
don't know if it's really clean tho
any other idea ?
Upvotes: 0