nowox
nowox

Reputation: 29096

Perl short form of regex capture

I would like to only get the first capture group into the same var. In fact, I am looking for a short form of:

$_ = $1 if m/$prefix($pattern)$suffix/;

Something like:

s/$prefix($pattern)$suffix/$1/a; ## Where a is the option I am looking for

Or even better:

k/$prefix($pattern)$suffix/; ## Where k is also an option I wish I can use...

This will avoid the need of matching all the text which leads to a more complicated line:

s/^.*$prefix($pattern)$suffix.*$/defined $1 ? $1 : ""/e;

Any clues?

This would be useful for this example:

push @array, {id => k/.*\s* = \s* '([^']+)'.*/};

instead of

/.*\s* = \s* '([^']+)'.*/;
my $id = '';
$id = $1 if $1;
push @array, {id => $id};

Edit:

I just found an interesting way, but if $1 is not defined I will get an error :(

$_ = (/$prefix($pattern)$suffix/)[0];

Upvotes: 1

Views: 165

Answers (3)

Miller
Miller

Reputation: 35198

Use a Conditional operator

my $var = /$prefix($pattern)$suffix/ ? $1 : '';

You always want to make sure that you regex matches before using a capture group. By using a ternary you can either specify a default value or you can warn that a match wasn't found.

Alternatively, you can use the list form of capture groups inside an if statement, and let your else output the warning:

if (my ($var) = /$prefix($pattern)$suffix/) {
    ...;
} else {
    warn "Unable to find a match";
}

Upvotes: 1

darch
darch

Reputation: 4311

In list context, the m// operator returns the captures as a list. This means you can do this:

($_) = m/$prefix($pattern)$suffix/;

or this:

my ($key, $value) = $line =~ m/^([^=]+)=([^=]+)$/;

Upvotes: 1

simbabque
simbabque

Reputation: 54323

You can use the /r switch to return the altered string instead of doing the substitution on the variable. There is no need to capture anything at all with that. Just get rid of the prefix and the suffix and add the result of that operation to your array.

use Data::Dump;

my @strings = qw( prefixcontent1suffix prefixcontent2suffix );
my @array = map { s/^prefix|suffix$//gr } @strings;

dd @array;

__END__

("content1", "content2")

If you want it to be configurable, how about this:

my $prefix = qr/.+\{\{/;
my $suffix = qr/\}\}.+/;
my @strings = ( '{fo}o-_@09{{content1}}bar42' );
my @array = map { s/^$prefix|$suffix$//gr } @strings;

dd @array;

__END__
"content1"

Upvotes: 1

Related Questions