Re: grep fields
by Enlil (Parson) on Sep 25, 2003 at 18:36 UTC
|
I believe what you are asking for is something very similar to this: use strict;
use warnings;
my @recs = ("a11:b21:c34",
"d32:e32:",
":g02:i6",
"k92:l9:m22");
my @good_recs = grep { (split/:/,$_)[1] =~ /2/ } @recs;
Where it will split the record, based on the second field, and see if it contains a 2, and if it does push the whole record unmodified record @good_recs.
-enlil
| [reply] [d/l] [select] |
Re: grep fields
by stajich (Chaplain) on Sep 25, 2003 at 18:33 UTC
|
I might be misunderstanding your question - do you want to build a new array of records which match in the nth column?
I would probably do this instead (and being explicit about where the variables come from always helps me later when I'm banging my head against the wall).
for my $rec ( @recs ) {
my @rec = split(/:/,$rec);
next unless @rec;
push (@goodrecs,$rec) if( $rec[$n] =~ /$pattern/ );
}
However, if you wanted to write grep statement to achieve your wish of matching the nth field (which I assume is delimited by ':' this should work (of course where $n and @recs are defined ahead of time).
my @goodrecs = grep { my @rec = split(/:/,$_);
$rec[$n] =~ /$pattern/; } @recs;
| [reply] [d/l] [select] |
Re: grep fields
by Cody Pendant (Prior) on Sep 25, 2003 at 21:25 UTC
|
I'm a bit concerned by this:
@rec = split /:/ or next;
Because it looks like you think that your split won't work, or will return zero or something if there aren't any colons in the string.
It will. It will split to an array with one item.
($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss')
=~y~b-v~a-z~s; print
| [reply] [d/l] [select] |
Re: grep fields
by Not_a_Number (Prior) on Sep 25, 2003 at 18:35 UTC
|
Is this what you mean?
push(@goodrecs, @rec) if ($rec[2] =~ /$that/);
dave
| [reply] [d/l] |
Re: grep fields
by sweetblood (Prior) on Sep 25, 2003 at 19:54 UTC
|
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. | [reply] [d/l] [select] |
|
|
If each field is seperated by a ":" then use the following
my @goodrecs = grep {$_=~/(.*:){3}foo@foobar.com/} @recs
| [reply] [d/l] |
|
|
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 | [reply] [d/l] |
|
|
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".) | [reply] [d/l] [select] |
Re: grep fields
by sweetblood (Prior) on Sep 26, 2003 at 14:15 UTC
|
foreach (@recs){push @goodrecs, $_ if (split /:/)[3] =~ /$addr/i}
Thanks Again! | [reply] [d/l] |