Re: Creating regex from arrays
by artist (Parson) on Jul 29, 2003 at 15:37 UTC
|
$regex = join '|' => map { "\($_\)" } @results;
if($_ =~ qr/$regex/){ print "$_" };
artist
| [reply] [d/l] |
|
|
Thanks. That worked great!
| [reply] |
Re: Creating regex from arrays
by Zaxo (Archbishop) on Jul 29, 2003 at 15:37 UTC
|
Something like this works,
my $re;
{
local $" = '|';
$re = qr/@results/;
}
The $" variable is interpolated between array elements in stringification.
After Compline, Zaxo | [reply] [d/l] |
|
|
| [reply] [d/l] [select] |
|
|
You're right, timtowtdi sitting on my shoulder. I do like that construction, though. IMO, it's more concise and less visually noisy. True, it depends on a trick from the second tier of quote operator details, but I think the sparse notation and localization of $" pretty well telegraph what the trick is.
I don't know if there is any performance benefit, other than what's obtained from constructing a compiled regex with qr//. That could as well be done with join. I've never benchmarked this.
A minor refinement of the code, to assign $re where it is declared:
my $re = do {
local $" = '|';
qr/@array/;
};
or, if metacharacters may be a problem,
my $re = do {
local $" = '|';
qr/@{[map {quotemeta} @array]}/;
};
After Compline, Zaxo
| [reply] [d/l] [select] |
|
|
I thought $" was one of the bad vars tht slows down all regex in your app once used?
-Waswas
| [reply] |
|
|
| [reply] [d/l] |
|
|
Re: Creating regex from arrays
by broquaint (Abbot) on Jul 29, 2003 at 15:47 UTC
|
Further to the answers above there's presuf from the Regex::PreSuf module which is tailored specifically to solving this problem e.g
use Regex::PreSuf;
print presuf("1234", "ABCD", "HIGL", "TOOA", "COOLIE");
__output__
(?:1234|ABCD|COOLIE|HIGL|TOOA)
It also rather niftily 'optimizes' (or 'compresses', depending on your view) the regular expression for overlapping words. See. the Regex::PreSuf docs for more info.
HTH
_________ broquaint | [reply] [d/l] |
Re: Creating regex from arrays
by liz (Monsignor) on Jul 29, 2003 at 15:49 UTC
|
Other monks have answered this.
I see only one caveat: if the character "I" can occur in your original array, you will have to escape that. Something like:
$tomatch = join( '|',map {s#|#\\|#s; $_} @results );
And yes, I prefer # over / for regexes to avoid the falling toothpick syndrome.
Liz | [reply] [d/l] |
|
|
| [reply] [d/l] |
|
|
map {s#|#\\|#s; $_} @results
I hope you don't have any other uses for @results as you've modified it in-place.
Perl doesn't have a great idiom for this. This type of mistake and several others are so common that I really think Perl should have a 'filter' keyword.
And thanks(++) for bringing up the important point about escaping regular expression metacharacters and prompting diotalevi's reply (which is what I'd use).
- tye
| [reply] [d/l] [select] |
|
|
Good point. Apart from using quotemeta, it would have been better to do:
$tomatch = join '|', map {local $_ = $_; s#\|#\\|#s; $_} @results;
When actually testing this, I found that my initial solution was flawed in another way: the initial pipe needs to be escaped as well! Does any monk have an idea why that is necessary?
Liz | [reply] [d/l] |
|
|
|
|
Re: Creating regex from arrays
by Kageneko (Scribe) on Jul 29, 2003 at 15:40 UTC
|
Hmm, you could do something like this:
my $results = join "|", @results;
my $results_re = qr/$results/;
...
if ( $name =~ /$results_re/ ) {
...
}
Undoubtedly, there is an easier way to do it, but that's what springs to mind. Using qr// allows you to compile the regex only once if you re-use the same results (and regex) over and over. | [reply] [d/l] |