qazwsx
qazwsx

Reputation: 26968

How to user Perl to find all instances of strings that match a regexp?

How to user Perl to find and print all strings that match a regexp?

The following only finds the first match.

$text="?Adsfsadfgaasdf.
?Bafadfdsaadsfadsf.
xcxvfdgfdg";

if($text =~ m/\\?([^\.]+\.)/) {
    print "$1\n";
}

EDIT1: /g doesn't work

#!/usr/bin/env perl

$text="?Adsfsadfgaasdf.
?Bafadfdsaadsfadsf.
xcxvfdgfdg";

if($text =~ m/\\?([^\.]+\.)/g) {
    print "$1\n";
}

$ ./test.pl 
?Adsfsadfgaasdf.

Upvotes: 10

Views: 11356

Answers (3)

Taras
Taras

Reputation: 920

In previous answer @TLP correctly wrote that matching should be in list context.

use Data::Dumper;

$text="?Adsfsadfgaasdf.
?Bafadfdsaa.
dsfadsf.
xcxvfdgfdg";

@arr = ($text =~ /\?([^\.]+\.)/g);

print Dumper(@arr);

Expected result:

$VAR1 = 'Adsfsadfgaasdf.';
$VAR2 = 'Bafadfdsaa.';

Upvotes: 2

TLP
TLP

Reputation: 67940

The problem is that the /g modifier does not use capture groups for multiple matches. You need to either iterate over the matches in scalar context, or catch the returned list in list context. For example:

use v5.10; # required for say()
$text="?Adsfsadfgaasdf.
?Bafadfdsaadsfadsf.
xcxvfdgfdg";

while ($text =~ /\?([^.]+\.)/g) {  # scalar context
    say $1;
}
for ($text =~ /\?[^.]+\./g) {     # list context
    say;               # match is held in $_
}

Note in the second case, I skipped the parens, because in list context the whole match is returned if there are no parens. You may add parens to select part of the string.

Your version, using if, uses scalar context, which saves the position of the most recent match, but does not continue. A way to see what happens is:

if($text =~ m/\?([^\.]+\.)/g) {
    print "$1\n";
}
say "Rest of string: ", substr $text, pos;

pos gives the position of the most recent match.

Upvotes: 10

zigdon
zigdon

Reputation: 15073

You seem to be missing the /g flag, which tells perl to repeat the match as many times as possible.

Upvotes: 0

Related Questions