in reply to grep fields

I guess I'm not making much sense due to rushing. But the idea is, that I want to populate a new array from the result of grepping another array based on the contents of a given field.
I'm not sure if using grep is a better choice than stepping thru the old array using a loop(foreach, etc) and splitting the individual records using split and then pushing the matching records into the new array if the given field matches what I'm looking for. But it seems more succinct.

Details:
I have a file that has 21 fields and 100's of records. I've sucked that file into an array (@recs), and I want any records(elements) from the @recs array in a new array(@goodrecs) that have a given email address in the 4th field. Each record(element) in the array @recs is ":" delimited. You could think of it like reading a passwd file into an array:

open(FH, "<passwd") or die $; my @recs = <FH>; etc....

so what I'd like to do is something like:

my @goodrecs = grep(/^.*?:{3}foo@foobar.com/, @recs);

This does not work. But That's the idea.

Replies are listed 'Best First'.
Re: Re: grep fields
by tbone (Beadle) on Sep 25, 2003 at 20:10 UTC
    If each field is seperated by a ":" then use the following
    my @goodrecs = grep {$_=~/(.*:){3}foo@foobar.com/} @recs
Re: Re: grep fields
by Not_a_Number (Prior) on Sep 25, 2003 at 20:53 UTC
    I want any records ... that have a given email address in the 4th field

    In that case, a direct string comparison is probably better (or at least simpler...) than a regex, along the lines of:

    my $adr = 'example@hotmail.com'; my @goodrecs; for (@recs){ push @goodrecs, $_ if (split /:/)[3] eq $adr; }

    This can doubtless be 'grepped', but I don't see why you should care...

    dave

Re: Re: grep fields
by graff (Chancellor) on Sep 26, 2003 at 03:42 UTC
    If there are 21 fields in each record, and the 4th field is an email address, and you want @goodrecs to hold just those records having a specific email address in that field, then consider this question:

    Is it ever possible that the email address you're searching for could occur in some other field but not in the 4th field? (I would assume that if "target@email.address" is in field 6 and not in field 4, then it's not a "goodrec".)

    If the records containing the target string always have that string in field 4, then you don't have to split:

    @goodrecs = grep /:target\@email\.address:/, @recs; # (note the delimiters are part of the match)
    But if that condition does not hold for your data, then split is the best approach, as others have suggested. And in that regard, if you're actually looking for one specific string at a time (as opposed to, say, all email strings that have digits before the "@"), then it may be better not to use a regex:
    @goodrecs = grep { @f=split/:/; $f[4] eq $target } @recs;
    This avoids getting "bigjoe@hotmail.com" and "dumbjoe@hotmail.com" when you were looking for just "joe@hotmail.com", in case that matters to you.

    (update: Maybe the latter snippet should say $f[3], if "field 4" is based on the first field being "field 1".)