First, interpolating an array into a character class in a regular expression.... You might think it to be as simple as /[@array]{n}/. But you would be wrong. Consider the following snippet:
Why on earth are you getting output of "AB C"? Well, remember that arrays interpolated into strings get 'list separation'. So you've interpolated the values of @group1 AND the space character (a few times) into the character class. The space gets in there as the record separator. That's easy to fix:use strict; use warnings; my @group1 = ('A','B','C','D'); my @group2 = ('E','F','G','H'); my $string="DEAB CDGHEF"; print "Match: $1\n" while $string =~ /([@group1]{4})/g;
placed before the regexp match will do it, but don't forget that the list separator has now been set to an empty string, and will remain so until "local" falls out of scope or you change it back. I used local in this case so that at very worst $" would revert back to its old self when its changed definition falls out of scope.local $" = '';
Since it's kinda ugly goofing around with $" just so that your regexp will work the way you want it to (will you really remember 6 months down the road that $" makes it so that your character class won't match space characters?) you should probably instead pre-concatenate the list contained in @group1 like this:
Ok, that's taken care of. But what if you are dead set on interpolating an array into a regexp character class, and more specifically, you really want to interpolate an array slice (as the question asked)? Brace yourself, you need a really ugly construct known as ...... er... I can't remember what it's called, which is all for the best because you should forget you saw it. Here's how to use it inside of a character class. You're not going to like it:my @group1 = ('A','B','C','D'); my $char_class1 = join "", @group1; my $string="DEABCDGHEF"; print "Match: $1\n" while $string =~ /([$char_class]{4})/g;
If the sheer ugliness and unmaintainability of that construct doesn't scare you away from it you should probably keep your day job.use strict; use warnings; my @group1 = ('A','B','C','D'); my @group2 = ('E','F','G','H'); my $string="DEABCDGHEF"; local $" = ''; print "Match: $1\n" while $string =~ /([@{[@group1[0..2],@group2[2,3]]}]{5})/g;
Here's how to do what you're trying to do without jumping through voodoo hoops:
use strict; use warnings; my @group1 = ('A','B','C','D'); my @group2 = ('E','F','G','H'); my $string="DEABCDGHEF"; my $group = join '', @group1[0..2], @group2[2,3]; print "Match: $1\n" while $string =~ /([$group]{5})/g;
Hope this helps! I'll leave it to you to adapt that final solution to your needs. It doesn't match the attempted functionality of your original code snippet, but learn from the technique; it should be the answer to your question, and can easily be applied to the snippet you used to illustrate your need.
Dave
In reply to Re: Using array slices during string matching
by davido
in thread Using array slices during string matching
by seaver
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |