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

Hello Monks , I am new to perl , I have a small question here : I have an input file that look like this :
profile FIRSTGRADE location here age 23 color brown sport n/a firstname Amy lastname Cako middlename M school n/a job n/a END profile SECONDGRADE location there age 24 color white sport n/a firstname James lastname Don middlename M school n/a job n/a END profile THIRDGRADE location here age 29 color brown sport n/a firstname Amy lastname Mando middlename S school n/a job n/a END
from my perl script I will be giving the profile name for example SECONDGRADE , then I will have to open that file and read to get the firstname lastname and middlename for the person in the SECONDGRADE which in this case will be :
firstname : James lastname : Don middlename : M
the order within the input file might change line before the other . Can someone help?
open ( input , "<input.doc" ) or die " couldn't "; while (<input>) { if(m/$grade/) { $subLine = $_ } } # not sure

Replies are listed 'Best First'.
Re: greping inside a file
by Plankton (Vicar) on Jan 19, 2004 at 21:41 UTC
    $cat easy.pl #!/usr/bin/perl -w use strict; my $grade = shift || die "usage:$0 <grade>\n"; # I'll just get the input from STDIN so I don't have to # worry about what the input file is. my $flag = 0; # set this to 1 when you see your grade # set it to 0 when you see END while(<>) { if ( $flag == 1 ) { print $_ if /^firstname /; print $_ if /^lastname /; print $_ if /^middlename /; $flag = 0 if /^END/; } $flag = 1 if /^profile $grade/; } $ cat easy.in profile FIRSTGRADE location here age 23 color brown sport n/a firstname Amy lastname Cako middlename M school n/a job n/a END profile SECONDGRADE location there age 24 color white sport n/a firstname James lastname Don middlename M school n/a job n/a END profile THIRDGRADE location here age 29 color brown sport n/a firstname Amy lastname Mando middlename S school n/a job n/a END $ ./easy.pl SECONDGRADE < easy.in firstname James lastname Don middlename M

    Plankton: 1% Evil, 99% Hot Gas.
      Nice one Plankton , thanks a lot
Re: greping inside a file
by pg (Canon) on Jan 19, 2004 at 21:38 UTC

    Take a look at Tie::File, and by using that you can easily turn the file into an array.

    Then go thru the small array you have, and use regexp, or just split on \s to get the keys and values.

    Hope the following sample can get you started.

    use Tie::File; use Data::Dumper; use strict; use warnings; print Dumper(foo('profile.txt')); sub foo { my (@a, %result); tie @a, 'Tie::File', shift; foreach (@a) { /(.*?)\s+(.*)/g; $result{$1} = $2 if (($1 eq 'firstname') or ($1 eq 'lastname') + or ($1 eq 'middlename')); } return \%result; }
Re: greping inside a file
by jweed (Chaplain) on Jan 19, 2004 at 21:43 UTC
    I would start by creating a has structure something like this:
    my %hash; my $profile; my $grade; my $key; my $value; open INPUT, "<input.doc or die "Couldn't open!"; LINE: while (<INPUT>) { if (/profile (\w+)/) { my $grade = $1; next LINE; } elseif ($_ eq 'END') { $hash{$grade} = $profile; undef $grade, $profile; } ($key,$value) = split; $$profile{$key} = $value; } close INPUT;
    Then, just access like this:
    $hash{THIRDGRADE}{location} etc.



    Code is (almost) always untested.
    http://www.justicepoetic.net/
      thanks
Re: greping inside a file
by bart (Canon) on Jan 19, 2004 at 22:30 UTC
    The first thing I think of when seeing this kind of "multiline match in file" problem, is the .. operator. Just as an alternative here's a demo of how you could do this, in rather few lines:
    use strict; my %profiles; { my $id; while(<DATA>) { if (my $count = ((($id) = /^profile\s+(.*?)\s*$/) .. /^END/)) +{ unless($count == 1 || $count =~ /E/) { # not first or last + line in group /^(\S+)\s+(.*?)\s*$/ and $profiles{$id}{$1} = $2; } } } } use Data::Dumper; print Dumper \%profiles; __DATA__ ... (data as in the root post follows)