How can I interpolate an interpolation array into a Perl regex?

Is it possible to do:

@foo = getPileOfStrings();

if($text =~ /@foo(*.?)@foo/)
{
 print "Sweet, you grabbed a $1! It lived between the foos!";
}

      

What is going on here I need $text =~ /($var1|$var2|$var3)(*.?)($var1.../

; I don't know how many values ​​there are, and I don't know the values ​​until runtime.

Matrix interpolation into a set of ORs seemed to be a straightforward way to do this, but it doesn't seem to work correctly and I end up in a tortuous set of code ... it all looks like it!

+2


source to share


2 answers


Use join

and qr//

:

my $strings = join "|", getPileOfStrings();
my $re      = qr/$strings/; #compile the pattern

if ($text =~ /$re(*.?)$re/)

      

If you want the same word to split stuff in the middle, say:

if ($text =~/($re)(.*?)\1/)

      

If the strings can contain characters that are considered special Perl regular expressions, you can use map

and quotemeta

to prevent the regular expression from using them:



my $strings = join "|", map quotemeta, getPileOfStrings();

      

And, as Michael Karman points out, if getPileOfStrings()

not designed to return the strings in the order you want them to match, you can use sort

to force the longest match first in the alternation (items earlier in the alternation will match Perl 5 first) :

my $strings = join "|" map quotemeta,
    sort { length $a <=> length $b } getPileOfStrings();

      

Remember to sort before running quotemeta, as "a..."

(length 4) will be converted to "a\\.\\.\\."

(length 6), which is longer than "aaaaaa"

(length 5).

+11


source


You can use Regex :: PreSuf :

my $re = presuf(getPileOfStrings());

      

Before proceeding, you may want to think about what you want to do for the following code:



#!/usr/bin/perl

use strict;
use warnings;

my @pile = qw(ar a);
my $string = 'ar5a';

my $pile = join '|', @pile;
my $re = qr/$pile/;

my ($captured) = $string =~ /$re(.*?)$re/;

print "$captured\n";

      

If you want to $captured

contain "r5"

, sort @pile

by the length of its elements before attaching, as in

my $pile = join '|', sort { length $a <=> length $b } @pile;

      

+4


source







All Articles