Bhavesh Shah
Bhavesh Shah

Reputation: 21

Perl - File Iteration and looking for specific matching data

I'm looking to iterate a file in Perl and if it finds a specific word then store the other lines following that which matches speific pattern. The ldap.txt file is pretty large in several Gigs.

user.txt

test1  
game  

ldap.txt

dn: uid=test1,ou=people,dc=admin,dc=local  
blah  
blah  
maillocaladdress: [email protected]  
maillocaladdress: [email protected]  
maillocaladdress: [email protected]  
some date  
some more data  
data  
dn: uid=game,ou=people,dc=admin,dc=local   
blah  
blah  
maillocaladdress: [email protected]   
maillocaladdress: [email protected]  
maillocaladdress: [email protected]  
some date  
some more data  
data  

and so on..

Open user.txt and iterate through each user and check each line on ldap.txt in dn: line. If matches, then store the value of all the lines matching maillocaladdress to the varialbe , I assume in hash key/value pari but here the values are more than one.

e.g.

test1 matches dn: uid=test1,ou=people,dc=admin,dc=local  

Store the following values for each user.

[email protected]  
[email protected]  
[email protected]  

code

#! /usr/bin/perl

use strict;
use warnings;

my $ldiffile = shift;
my %emails;

open my $US, '<', 'users2.txt'
                  or die "Could not Open the file users2.txt: $!";

open my $FH, '<', $ldiffile
                 or die "Could not Open the file $ldiffile: $!";

chomp(my @users = <$US>);
#print "@users \n";

foreach my $uid (@users) {
print "$uid \n";
#       while ( chomp(my $line = <$FH>) ) {
        while (my $line = <$FH>) {
        chomp ($line);
                if ( $line =~ /dn: uid=$uid,ou=People,dc=admin,dc=local/i ) {
                print "$line \n";
                        if ( $line =~ /mailLocalAddress: ([\w\.\-\_\@]+)/ ) {
                                print "<<<< $line >>>> \n";
                                push ( @{$emails{$uid}}, $1 );
                        }
                }
        }
}

Upvotes: 0

Views: 82

Answers (2)

choroba
choroba

Reputation: 241998

Hash the user list. Then, iterate over the second file. Remember what user you are currently parsing ($user). If you see an email address, store it.

#!/usr/bin/perl
use warnings;
use strict;

my %users;
open my $USER, '<', 'user.txt' or die $!;
while (<$USER>) {
    s/\s*$//;               #/ Sample input contains trailing whitespace.
    undef $users{$_};
}

my $user = q();
open my $LDAP, '<', 'ldap.txt' or die $!;
while (<$LDAP>) {
    s/\s*$//;
    $user = $1 if /dn: uid=(.*?),ou=people,dc=admin,dc=local/;
    push @{ $users{$user} }, $1 if exists $users{$user} 
                                and /maillocaladdress: (.*)/;
}

for my $user (keys %users) {
    print "$user\n\t";
    print join "\n\t", @{ $users{$user} };
    print "\n";
}

Upvotes: 1

Miller
Miller

Reputation: 35208

You have some likely flaws in your program. You're attempting to iterate over the file for each of the @users, but instead you're just looping through the file for the first user only.

What you should do instead is just loop over the file and pull out userids and match them against your list of accepted users. The following should do what you want:

#!/usr/bin/perl

use strict;
use warnings;
use autodie;

open my $US, '<', 'users2.txt';
chomp(my @users = <$US>);
close $US;
my %isuser = map {$_ => 1} @users;

my %emails;

my $userid = '';
while (<>) {
    chomp;
    if (/^dn: uid=([^,]*)/) {
        $userid = $1;
        $userid = '' if !/,ou=People,dc=admin,dc=local/;

    } elsif ($isuser{$userid}) {
        if (/mailLocalAddress: ([\w.-_@]+)/i) {
            print "$userid - <<<< $_ >>>> \n";
            push @{$emails{$userid}}, $1;
        }
    }
}

Also, your regex to test for mailLocalAddress has capital letters where as your example data does not. Therefore put a /i flag on the regex.

Upvotes: 0

Related Questions