Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

data comparison

by topman (Initiate)
on Nov 05, 2007 at 10:23 UTC ( [id://648985]=perlquestion: print w/replies, xml ) Need Help??

topman has asked for the wisdom of the Perl Monks concerning the following question:

hello all,
i have daveloped a perl script to compare 1000users to a large data base of 1 lakh users,in which each the data is such that each user has login name ,description,e-mail address etc associated with him,but i am having only the names of the 1000 users ,so what my job ,is to find all the details of these 1000 users from the 1 lakh users data base,like their respective departments,emial address etc;i had written a code for it ..but what the problem is that when i run it i get the error message...uninitialized value in string concatenation i am adding my code below...can any one help me to fix it thanks in advance
#!/usr/bin/perl -w use strict; use Net::LDAP; use Data::Dumper; my $username="CN=xxxxx,OU=MUC-Users,OU=Users,OU=MUC,DC=eu,DC=xxxxxx,DC +=com"; my $password='xxxx"==('; # global data my $ad; my %users = (); #my $someotheruser =(); #my $someotheruse; #my $fulluser = (); # Collect all data from LDAP my %ldap_server = (yy => 'xxxxx.com', dd => 'lxxxxxx.com', cc => 'xxxx +xxxxxx.com'); for my $region (sort keys %ldap_server) { # we need to authenticate in each region separately $ad = Net::LDAP->new($ldap_server{$region}) or die ("Could not con +nect to LDAP server $ldap_server{$region}: $@"); print "INFO: Connected to server $ldap_server{$region}\n"; my $return = $ad->bind ($username, password=>$password) or die ("C +ould not bind to LDAP server as user $username: $@"); $return->code && die $return->error; print "INFO: Bound to server $ldap_server{$region} as user $userna +me\n"; # collect all user info in region _get_users ($region, ''); # unbind from LDAP server again $ad->unbind; } #my $i = 0; foreach (keys %users) { $i++ }; print "$i users found\ +n"; my $f =""; foreach my $user (values %users) { $f = "$user->{'sn'}" . "$user->{'givenName'}"; #print$f; my @data; # open file open(FILE, "good.txt") or die("Unable to open file"); # read file + into an array @data = <FILE>; # close fil +e close(FILE); my $e =""; foreach $e (@data) { if( $f = $e ) { print$user->{'sn'}.$user->{'givenName'}.print$user->{'descript +ion'}.$user->{'mail'}; } } } exit; sub _get_users { my ($region, $prefix) = @_; my @patternlist = qw(a b c d e f g h i j k l m n o p q r s t u v w + x y z 0 1 2 3 4 5 6 7 8 9 _ -); #my @patternlist = qw(a); for my $pattern (@patternlist) { my $return = $ad->search(base=>"DC=$region,DC=xxxxxxx,DC=com", filter=>"(&(objectCategory=user)(cn=$ +prefix$pattern*))", scope=>'sub') or die ("Could not search LDAP server: $@"); my $error = $return->code; if ($error) { if ($error == 4) { print "Sizelimit exceeded for Region $region, $prefix$ +pattern\* .. extending\n"; _get_users ($region, "$prefix$pattern"); } else { print $return->error; } } else { #print "Region $region, $prefix$pattern\*: ", $return->cou +nt, " users found\n"; } my @entries = $return->entries; foreach my $entry (@entries) { my $user = (); foreach (qw(cn sn givenName department Ihj-klDir-GlobalID +description mail I-eDjr-AccountType distinguishedName userWorkstation s)) { $user->{$_} = $entry->get_value($_); } my @array = $entry->get_value('memberOf'); $user->{'memberOf'} = \@array; $users{$entry->get_value('distinguishedName')} = $user; } } }

20071105 Janitored by Corion: Added formatting, code tags, as per Writeup Formatting Tips

Replies are listed 'Best First'.
Re: data comparison
by Corion (Patriarch) on Nov 05, 2007 at 10:58 UTC

    I'm pretty sure that Perl warns you about this line:

    if( $f = $e ) {

    Most likely you want to use one of the two equality comparison operators, == or eq instead of using an assignment expression here.

Re: data comparison
by shoness (Friar) on Nov 05, 2007 at 13:41 UTC
    I learned what a Lakh is today!
    Very Perlish!
    It's like typing $/ instead of $INPUT_RECORD_SEPARATOR. :-)
Re: data comparison
by talexb (Chancellor) on Nov 05, 2007 at 18:41 UTC
      .. but what the problem is that when i run it i get the error message...uninitialized value in string concatenation ..

    That usually occurs when you're putting an undefined variable into a string. Perl deals with this nicely and just puts a null string '' for you, but it's a warning that you probably have something wrong in your code. There's usually a line number along with that message -- check that part of your code.

    I have a few suggestions for you that will probably help you in your quest to become a better developer.

    • Be neat If you're going to write source code, you are writing for two audiences: computers (who don't care what it looks like) and humans (who appreciate regularly formatted code). Even before we start talking about use strict, we need to make sure this is clear.
    • Be organized You need to lay out what the script is doing, and what your plan is for achieving that. A few comments will help that aim. No, you probably don't need to do that for a two line script. However, anything moderately complicated will benefit from this approach.
    • Let Perl help you When you see a warning from Perl, that's a sign that you have missed something. If you clean up your code so that Perl can't find anything to complain about, the code may still not work, but at least it's doing the wrong thing with the right syntax.
    • Perl is not like other languages Perl can help you do clever things. In your code, you have
      my @entries = $return->entries; foreach my $entry (@entries) { ..
      So you called this function to get a list of entries, put it into an array, and in the very next step you start stepping through that array. That's a memory expense that you don't need. Instead,
      foreach my $entry ($return->entries) {
      will do exactly the same thing.

    Your approach to the problem makes sense -- you want to scan three servers and find all occurrences of the 1000 users. But you appear to be collecting that information as you go, rather than outputting it as you find it. Why is that?

    I would suggest you use a hash of hashes (HoH) to group your users together -- so you'd have the names grouped together by first letter -- and then search as you've done on the same first letter, and check each entry to see if there's a match. The CPAN page on Net::LDAP says that you can use a callback function, so that might be a timesaver -- you can search for the users, specify a callback function and have that function stuff the matches into an array; once you return from the search, dump out the array of matches, and go on to the next letter. You can even limit the number of matches during your development, so as to not load up this Production machine.

    Alex / talexb / Toronto

    "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Re: data comparison
by jhourcle (Prior) on Nov 05, 2007 at 18:21 UTC

    A suggestion on a possible code optimization:

    From what you've described, you have 100,000 entries in LDAP, and 1000 entries in the file. The way your loop works, you're asking LDAP for all of the entries, and then opening the file for _each_entry_ to see if any of the lines in the file match the entry.

    At a minimum -- open the file once, and generate a hash using each line in the file as a hash key -- then just test for existance in the hash. (note -- besides the issue with using '=' to compare, as already mentioned, you'll most likely also want to chomp the line to remove line endings)

    Even better -- for each one of the lines in the file, extract the sn and givenName, and then do an LDAP search for entries matching those values ... yes, it's 1000 LDAP queries, but they should hopefully be relatively small, and prevent you from needing to process 100,000 records.

Re: data comparison
by apl (Monsignor) on Nov 05, 2007 at 10:52 UTC
    I regret I can't help you (I haven't worked with LDAP). For my brother monks who can, I suggest you bracket your code with <code> and </code>.

    This will make your program much more readable.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://648985]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (5)
As of 2024-04-20 00:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found