How can I extract the matches from the Perl match operator into variables?
Asked Answered
G

7

17

If I have a match operator, how do I save the parts of the strings captured in the parentheses in variables instead of using $1, $2, and so on?

... = m/stuff (.*) stuff/;

What goes on the left?

Gruver answered 2/11, 2009 at 13:7 Comment(3)
I've completely replaced the question based on joachim's comments to other answers. It's not a regex question.Doormat
With the question phrase like that, it makes sense that you seem to have downvoted my answer.Quechuan
@brian, your edit is probably more concise, as my question was purely about the syntax to use with and around the m// operator rather than anything to do with the regexp itself. My bad. But I'd like to put the word 'extract' back in there somewhere, as that's what I'll google for when I forget how to do this!Gruver
G
38

The trick is to make m// work in list context by using a list assignment:

 ($interesting) = $string =~ m/(interesting)/g;

This can be neatly extended to grab more things, eg:

 ($interesting, $alsogood) = $string =~ m/(interesting) boring (alsogood)/g;
Gruver answered 2/11, 2009 at 13:9 Comment(2)
True. Though the bit I always get stuck on is the syntax to get stuff into named variables, rather than the regexp side of things, so I skimped on the regexp part of the example and answer.Gruver
Also @interesting = $string ...?Boniface
Q
9

Use the bracketing construct (...) to create a capture buffer. Then use the special variables $1, $2, etc to access the captured string.

if ( m/(interesting)/ ) {
    my $captured = $1;
}
Quechuan answered 2/11, 2009 at 13:24 Comment(5)
You don't need a capturing group when you want the whole expression. Just use $0 instead.Maurita
@Peter: I think you must have confused $0, the name of the current program, with something else.Doormat
... with something completely else, in fact.Quechuan
the something else being $& (use of which has performance implications to your whole program)Greig
Perl v5.10 added ${^MATCH} to replace $& so you didn't get hit with the global performance penalty. Up to v5.18, you had to activate that with the /p flag (like, m/PATTERN/p), but with v5.20 and later you get ${^MATCH} for free.Doormat
H
7

Usually you also want to do a test to make sure the input string matches your regular expression. That way you can also handle error cases.

To extract something interesting you also need to have some way to anchor the bit you're interested in extracting.

So, with your example, this will first make sure the input string matches our expression, and then extract the bit between the two 'boring' bits:

$input = "boring interesting boring";
if($input =~ m/boring (.*) boring/) {
    print "The interesting bit is $1\n";
}
else {
    print "Input not correctly formatted\n";
}
Hypsography answered 2/11, 2009 at 13:21 Comment(0)
A
3

@strings goes on the left and will contain result, then goes your input string $input_string. Don't forget flag g for matching all substrings.

my @strings=$input_string=~m/stuff (.*) stuff/g;
Armlet answered 18/3, 2016 at 8:30 Comment(0)
S
2

You can use named capture buffers:

if (/ (?<key> .+? ) \s* : \s* (?<value> .+ ) /x) { 
    $hash{$+{key}} = $+{value};
}
Simonson answered 13/11, 2009 at 8:4 Comment(0)
I
0

$& - The string matched by the last successful pattern match (not counting any matches hidden within a BLOCK or eval() enclosed by the current BLOCK).

#! /usr/bin/perl

use strict;
use warnings;

my $interesting;
my $string = "boring interesting boring";
$interesting = $& if $string =~ /interesting/;
Isoelectronic answered 2/11, 2009 at 14:16 Comment(2)
Don't use $&. Especially in this case, if you are matching literal text, you don't have to match at all. You already know the answer without $&.Doormat
Perl v5.10 added ${^MATCH} to replace $& so you didn't get hit with the global performance penalty. Up to v5.18, you had to activate that with the /p flag (like, m/PATTERN/p), but with v5.20 and later you get ${^MATCH} for free.Doormat
D
0

The usual way to get all the captures is to list assign the result of m//:

my @matches = /PATTERN/;

Perl v5.26 added the @{^CAPTURE} variable:

if( /PATTERN/ ) {
    print "matches were @{^CAPTURE}\n";
    }
Doormat answered 21/7 at 21:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.