Perl - 文件迭代并查找特定的匹配数据

时间:2014-03-24 21:47:17

标签: regex perl

我希望在Perl中迭代一个文件,如果找到一个特定的单词,那么将其他行存储在符合特定模式的行之后。 ldap.txt文件在几个Gigs中相当大。

user.txt

test1  
game  

ldap.txt

dn: uid=test1,ou=people,dc=admin,dc=local  
blah  
blah  
maillocaladdress: test1@example.com  
maillocaladdress: test.team@example.com  
maillocaladdress: test11@example.com  
some date  
some more data  
data  
dn: uid=game,ou=people,dc=admin,dc=local   
blah  
blah  
maillocaladdress: game@example.com   
maillocaladdress: game.test@example.com  
maillocaladdress: game-test@example.com  
some date  
some more data  
data  

依旧......

打开user.txt并遍历每个用户并检查dn:line中ldap.txt上的每一行。如果匹配,则将匹配maillocaladdress的所有行的值存储到varialbe,我假设在散列键/值pari中,但这里的值大于1。

e.g。

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

为每个用户存储以下值。

test1@example.com  
test.team@example.com  
test11@example.com  

#! /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 );
                        }
                }
        }
}

2 个答案:

答案 0 :(得分:1)

哈希用户列表。然后,迭代第二个文件。记住您当前正在解析的用户($ user)。如果您看到电子邮件地址,请将其存储。

#!/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";
}

答案 1 :(得分:0)

你的程序中可能存在一些缺陷。您试图为每个@users迭代文件,但是您只是为第一个用户循环遍历该文件。

您应该做的只是循环遍历文件并提取用户ID并将其与您接受的用户列表进行匹配。以下应该做你想要的:

#!/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;
        }
    }
}

另外,测试mailLocalAddress的正则表达式是大写字母,而示例数据则没有。因此在正则表达式上放置/i标志。