user3008283
user3008283

Reputation: 17

PERL: parsing a multiple line result

I was looking for the best way to parse some text results which appear on multiple line.

The results are coming from ldapSearch and are presented in such a way:

sn: 1234

name: frank

mail: [email protected]

phone: 123 456 7890

sn: 2345

name: john

mail: [email protected]

phone: 123 456 7890

Although this can easily be done by putting all lines in an @array and then using split to get the actual value, my problem is that depending on the specific record, some lines might be omitted when dont contain any value.

So some records might show up as:

sn: 3456

name: mary

phone: 234 567 8901 (missing mail attribute)

So in this case, blindly reading for the position number won't help. Any idea of a way to actually search for the line name and then read the result?

Many thanks, Frank

Upvotes: 0

Views: 250

Answers (3)

fugu
fugu

Reputation: 6578

This might achieve what you're after:

#!/usr/bin/perl -w
use strict;

my $infile = 'in.txt';
open my $input, '<', $infile or die "Can't open to $infile: $!";

Input:

sn: 1234
name: frank
mail: [email protected]
phone: 123 456 7890
sn: 2345
name: john
mail: [email protected]
phone: 123 456 7890
name: bob # This entry has only a name and number
phone: 44 4232 232

-

while (<$input>){
    chomp;
    my ($sn) = /sn: (\d+)/;
    print "Sn: $sn\n" if $sn;
    my ($name) = /name: (\w+)/;
    print "Name: $name\n" if $name; 
    my ($email) = /mail: (.+\@.+)/;
    print "Email: $email\n" if $email;  
    my ($phone) = /phone: (.*)/;
    print "Phone: $phone\n" if $phone;

    # do something with the variables...

}

Outputs:

Sn: 1234
Name: frank
Email: [email protected]
Phone: 123 456 7890
Sn: 2345
Name: john
Email: [email protected]
Phone: 123 456 7890
Name: bob
Phone: 44 4232 232

Upvotes: 0

Rory Hunter
Rory Hunter

Reputation: 3460

I would iterate over the lines, looking for an indication that the current entity has changed:

#!/usr/bin/perl -w

use strict;
use warnings;

my %records;
my $sn = 'unknown';

while (my $line = <>) {
    chomp $line;
    next unless $line;

    my ($key,$value) = $line =~ m/^(\w+):\s*(.*)/;

    if ($key eq 'sn') {
        $sn = $value;
    }

    $records{$sn}->{$key} = $value;
}

use Data::Dumper;

print Dumper( \%records );

Upvotes: 0

mpapec
mpapec

Reputation: 50637

You can read all attributes into hash,

chomp(@array);
my %user = map { split /\s*:\s*/, $_, 2 } @array;

# print $user{name}, $user{phone}

Upvotes: 1

Related Questions