Reputation: 21
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.
test1
game
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
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
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