How to capture every match in a global regex substitution?

Viewed 126

I realize it is possible to achieve this with a slight workaround, but I am hoping there is a simpler way (since I often make use of this type of expression).

Given the example string:

my $str = "An example: sentence!*"

A regex can be used to match each punctuation mark and capture them in an array. Thereafter, I can simply repeat the regex and replace the matches as in the following code:

push (@matches, $1), while ($str =~ /([\*\!:;])/);
$str =~ s/([\*\!:;])//g;

Would it be possible to combine this into a single step in Perl where substitution occurs globally while also keeping tabs on the replaced matches?

5 Answers

You can embed code to run in your regular expression:

my @matches;
my $str = 'An example: sentence!*';
$str =~ s/([\*\!:;])(?{push @matches, $1})//g;

But with a match this simple, I'd just do the captures and substitution separately.

Use:

my $str = "An example: sentence!*";
my @matches = $str =~  /([\*\!:;])/g;
say Dumper \@matches;
$str =~ tr/*!:;//d;

Output:

$VAR1 = [
          ':',
          '!',
          '*'
        ];

Yes, it's possible.

my @matches;
$str =~ s/[*!:;]/ push @matches, $&; "" /eg;

However, I'm not convinced that the above is faster or clearer than the following:

my @matches = $str =~ /[*!:;]/g;
$str =~ tr/*!:;//d;

Is that what you're looking for ?

my ($str, @matches) = ("An example: sentence!*");

#first method : 
($str =~ s/([\*\!:;])//g) && push(@matches, $1);

#second method : 
push(@matches, $1) while ($str =~ s/([\*\!:;])//g);

Try:

my $str = "An example: sentence!*";

push(@mys, ($str=~m/([^\w\s])/g));

print join "\n", @mys;

Thanks.

Related