开发者

Perl extract matches from list

开发者 https://www.devze.com 2023-04-11 04:39 出处:网络
I\'m fairly new to perl but not to scripting languages. I have a file, and I\'m trying to extract just one portion of each line that matches a regex. For example, given the file:

I'm fairly new to perl but not to scripting languages. I have a file, and I'm trying to extract just one portion of each line that matches a regex. For example, given the file:

FLAG(123)
FLAG(456)
Not a flag
FLAG(789)

I'd like to extract the list [123, 456, 789]

The regex is obviously /^FLAG\((\w+)/. My questi开发者_如何学运维on is, what's an easy way to extract this data in perl?

It's obviously not hard to set up a loop and do a bunch of =~ matches, but I've heard quite a bit about perl's terseness and how it has an operator for everything, so I'm wondering if there's a slick, simple way to do this.

Also, can you point me towards a good perl reference where I can find out slick ways to do other things like this when the opportunity next arises? There are many perl resources on the web, but 90% of them are too simple and the other 10% I seem to lose the signal in the noise.

Thanks!


Here's how I would do it... Did you learn anything new and/or helpful?

my $file_name = "somefile.txt";
open my $fh, '<', $file_name or die "Could not open file $file_name: $!";

my @list;
while (<$fh>)
{
    push @list, $1 if /^FLAG\((\w+)/;
}

Things worth pointing out:

  1. In a while loop condition (and ONLY in a while loop condition), reading from a filehandle will set the value to $_ and check that the file was read automatically.
  2. A statement can be modified by attaching an if, unless, for, foreach, while, or until to the end of it. Then it works as a conditional or loop on that one statement.
  3. You probably know that regex capture groups are stored in $1, $2, etc., but you might not have known that the statement will work even if the statement has an if suffix. The if is evaluated first, so push @list, $1 if /some_regex/ makes sense and will do the match first, assigning to $1 before it is needed in the push statement.


Assuming that you have all of the data together in a single string:

my @matches = $data =~ /^FLAG\((\w+)/mg;

The /g modifier means to match as many times as possible, the /m makes ^ match after any newline (not only at the beginning of the string) and a match in list context returns all of the captures for all of those matches.

If you're reading the data in line-by-line then Platinum Azure's solution is the one you want.


map is your friend here.

use strict;
use warnings;
use File::Slurp;

my @matches = map { /^FLAG\((\w+)/ } read_file('file.txt');
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号