Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

map problems

0 views
Skip to first unread message

Natxo Asenjo

unread,
May 16, 2013, 3:57:55 PM5/16/13
to begi...@perl.org
hi,

in a ldap script where I get a list of values of a multivalued attribute like this:

@memberof = qw( cn=group1,cn=xxx,dc=domain,dc=tld cn=group2,cn=xxx,d=domain,dc=tld etc etc) ;

I would like to use map to convert the list of elements to
@memberof = qw( group1 group2 group3 etc etc )

This is the code I have tried to capture the first string after the first '=' in the $1 variable

@memberof = map { s/^cn=(.*),.*$/$1/g; $_ } @memberof;
    for ( @memberof ) {
        print "[$_]" . " " ;
    }

but this snippet strangely cuts the start and the end of every array element beginning and end so I get this:

[group1,cn=xxx,dc=domain] [group2,cn=xxxx,dc=domain]

so it is obviously not working. Is there a way to do this with map or do I just have to process the array in a for loop and fill a new array with the values? Just curious

TIA,
--
Groeten,
natxo

Jim Gibson

unread,
May 16, 2013, 5:14:30 PM5/16/13
to Perl Beginners
The * in (.*) is "greedy", meaning the Perl regular expression engine will try to match as much as possible in each string after it finds the substring 'cn='. To make it "non-greedy", put a question mark after the quantifier: s/^cn=(.*?),/$1/

Note that the '.*$' characters ending your pattern are completely superfluous and will not affect the match or substitution in any way.

Another way to achieve the same results is to match all non-comma characters up to the first comma: s/^cn=([^,]*),/$1/

Also note that since $_ inside the map block is an alias to the array members, you are modifying the array members in place, and you do not need to assign the result to the original array. Since using map in void context can be confusing, many Perl programmers would write it this way:

s/^cn=([^,]*),/$1/ for @memberof;

Since I wouldn't normally want to modify the original array, I might do it this way, taking advantage of the fact that the match operator (m//) in list context returns a list of the captured matches, so no substitution is required:

my @newmemberof = map { m/^cn=([^,]*),/g } @memberof;

timothy adigun

unread,
May 16, 2013, 5:27:08 PM5/16/13
to Natxo Asenjo, Perl Beginners

Hi Natxo,
Please see my comment below:

On Thu, May 16, 2013 at 8:57 PM, Natxo Asenjo <natxo....@gmail.com> wrote:
hi,

in a ldap script where I get a list of values of a multivalued attribute like this:

@memberof = qw( cn=group1,cn=xxx,dc=domain,dc=tld cn=group2,cn=xxx,d=domain,dc=tld etc etc) ;

 Since you use  "qw", there is no need to still separate the element of your array with comma.

I would like to use map to convert the list of elements to
@memberof = qw( group1 group2 group3 etc etc )

  Does etc etc here mean words like group...?
 

This is the code I have tried to capture the first string after the first '=' in the $1 variable

@memberof = map { s/^cn=(.*),.*$/$1/g; $_ } @memberof;
    for ( @memberof ) {
        print "[$_]" . " " ;
    }

but this snippet strangely cuts the start and the end of every array element beginning and end so I get this:

[group1,cn=xxx,dc=domain] [group2,cn=xxxx,dc=domain]

so it is obviously not working. Is there a way to do this with map or do I just have to process the array in a for loop and fill a new array with the values? Just curious


    Understanding for/foreach loop could help in a way to understand and use map function.
 
    Please see below one of the way of doing what you intended:

  [CODE]

  use warnings;
  use strict;

my @memberof =
  qw( cn=group1 cn=xxx dc=domain dc=tld cn=group2 cn=xxx d=domain dc=tld etc etc);

 ## using for loop

for my $grp (@memberof) {
    if ( $grp =~ m/(?<=\=)(.+)/ ) {
        my $matched = $1;
        print $matched, $/ if $matched =~ /group/;
    }
}

## use map function

@memberof = map {
    if (/(?<=\=)(.+)/) {
        my $matched = $1;
        $matched, $/ if $matched =~ /group/;
    }
} @memberof;

print @memberof;

  [/CODE]

 Hope this helps.

TIA,
--
Groeten,
natxo



--
Tim

Natxo Asenjo

unread,
May 16, 2013, 5:32:02 PM5/16/13
to begi...@perl.org
On Thu, May 16, 2013 at 11:14 PM, Jim Gibson <jimsg...@gmail.com> wrote:
The * in (.*) is "greedy", meaning the Perl regular expression engine will try to match as much as possible in each string after it finds the substring 'cn='. To make it "non-greedy", put a question mark after the quantifier: s/^cn=(.*?),/$1/


yes, I had forgotten that. Thanks for your kind explanation.

--
groet,
natxo


Peter Gordon

unread,
May 17, 2013, 3:28:09 AM5/17/13
to begi...@perl.org
On Thu, 16 May 2013 21:57:55 +0200, Natxo Asenjo wrote:
>in a ldap script where I get a list of values of a multivalued >attribute like this:
 
>@memberof = qw( cn=group1,cn=xxx,dc=domain,dc=tld >cn=group2,cn=xxx,d=domain,dc=tld etc etc) ;
 
>I would like to use map to convert the list of elements to
>@memberof = qw( group1 group2 group3 etc etc )

I'm not clear on what you are trying to achieve.  Your problem is probably in the RE.  The comma in your RE is greedy.
A "?" within the brackets makes it non greedy.  Read
for a good explanation of this subject.
The code below illustrates the difference.
 
#!/usr/bin/perl -w
use 5.14.0;
my $str = "cn=group1,cn=xxx,dc=domain,dc=tld cn=group2,cn=xxx,d=domain,dc=tld";
$str =~ /^cn=(.*),.*/;
say $1;
$str =~ /^cn=(.*?),.*/;
say $1;
__END__
*** Output ***
group1,cn=xxx,dc=domain,dc=tld cn=group2,cn=xxx,d=domain
group1


--
Peter Gordon, pet...@netspace.net.au on 05/17/2013
0 new messages