简体   繁体   中英

Perl regex to extract multiple matches from string

I have a string for example

id:123,createdby:'testuser1',"lastmodifiedby":'testuser2'.....

I want to extract the 2 user names (testuser1, testuser2) and save it to an array.

You don't need to do everything in one pattern. Do something simple in multiple matches:

my $string = qq(id:123,createdby:'testuser1',"lastmodifiedby":'testuser2');

my( $created_by )       = $string =~ /,createdby:'(.*?)'/;
my( $last_modified_by ) = $string =~ /,"lastmodifiedby":'(.*?)'/;

print <<"HERE";
Created:          $created_by
Last modified by: $last_modified_by
HERE

But, this looks like comma-separated data, and the data that you show are inconsistently quoted. I don't know if that's from you typing it out or it's your actual data.

But, it also looks like it might have come from JSON. It that's true, there are much better ways to extract data.

Try this

use strict;
use warnings;

my $string = q[id:123,createdby:'testuser1',"lastmodifiedby":'testuser2'....];

my @matches = ($string =~ /,createdby:'(.+?)',"lastmodifiedby":'(.+?)'/) ;

print " @matches\n";

Outputs

testuser1 testuser2

User requirements changed to allow coping with missing files. To deal with that, try this

use strict;
use warnings;

my $string1 = q[id:123,createdby:'testuser1',"lastmodifiedby":'testuser2'....];
my $string2 = q[id:123,createdby:'testuser1'....] ;

for my $s ($string1, $string2)
{
    my @matches = ( $s =~ /(?:createdby|"lastmodifiedby"):'(.+?)'/g ) ;
    print "@matches\n";
}

Outputs

testuser1 testuser2
testuser1

Problem description does not give enough details, inside the string quoting is not consistent.

As already stated the string can be part of JSON block and in such case should be handled by other means. Perhaps this assumption is correct but it not clearly stated in the question.

Please read How do I ask a good question? , How to create a Minimal, Reproducible Example .

Otherwise assumed that quoting is just a typing error. A bigger data sample and better problem description would be a significant improvement of the question.

Following code sample demonstrates one of possible approaches to get desired result and assumes that data fields does not includes , and : (otherwise other approach to process data must be in place).

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my($str,%data,@arr);

$str = "id:123,createdby:'testuser1','lastmodifiedby':'testuser2'";
$str =~ s/'//g;
%data = split(/[:,]/,$str);

say Dumper(\%data);

@arr = ($data{createdby},$data{lastmodifiedby});

say Dumper(\@arr);

Output

$VAR1 = {
          'id' => '123',
          'createdby' => 'testuser1',
          'lastmodifiedby' => 'testuser2'
        };

$VAR1 = [
          'testuser1',
          'testuser2'
        ];

Other approach could be as following

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my($str,$re,@data,@arr);

$str  = "id:123,createdby:'testuser1',\"lastmodifiedby\":'testuser2'";
@data = split(',',$str);
$re   = qr/(createdby|lastmodifiedby)/;

for ( @data ) {
    next unless /$re/;
    s/['"]//g;
    my($k,$v) = split(':',$_);
    push @arr, $v;
}

say Dumper(\@arr);

Output

$VAR1 = [
          'testuser1',
          'testuser2'
        ];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM