Question

I am trying to simultaneously remove and store (into an array) all matches of some regex in a string. To return matches from a string into an array, you could use

my @matches = $string=~/$pattern/g;

I would like to use a similar pattern for a substitution regex. Of course, one option is:

my @matches = $string=~/$pattern/g;
$string =~ s/$pattern//g;

But is there really no way to do this without running the regex engine over the full string twice? Something like

my @matches = $string=~s/$pattern//g

Except that this will only return the number of subs, regardless of list context. I would also take, as a consolation prize, a method to use qr// where I could simply modify the quoted regex to to a sub regex, but I don't know if that's possible either (and that wouldn't preclude searching the same string twice).

Was it helpful?

Solution

Perhaps the following will be helpful:

use warnings;
use strict;

my $string  = 'I thistle thing am thinking this Thistle a changed thirsty string.';
my $pattern = '\b[Tt]hi\S+\b';

my @matches;
$string =~ s/($pattern)/push @matches, $1; ''/ge;

print "New string: $string; Removed: @matches\n";

Output:

New string: I   am    a changed  string.; Removed: thistle thing thinking this Thistle thirsty

OTHER TIPS

Here is another way to do it without executing Perl code inside the substitution. The trick is that the s///g will return one capture at a time and undef if it does not match, thus quitting the while loop.

use strict;
use warnings;
use Data::Dump;

my $string = "The example Kenosis came up with was way better than mine.";
my @matches;

push @matches, $1 while $string =~ s/(\b\w{4}\b)\s//;

dd @matches, $string;

__END__

(
  "came",
  "with",
  "than",
  "The example Kenosis up was way better mine.",
)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top