Reads from a flat file of three columns, delimited by at least one tab character. Filters the three columns based on input; returns list of corresponding emails. Arguments passed like key=value
or key=
for blank.
#!/bin/perl
use warnings;
use strict;
sub get_list {
my $cols = {'list'=>0, 'email'=>1, 'sub'=>2};
my $list = '[a-z0-9_\- ]+';
my $email = '[a-z0-9@\._\-]+';
my $subls = '[a-z0-9\. ]+';
my $return = $cols->{'email'};
foreach (@ARGV) {
my ($key, $value) = split '=';
$value = q{} if not defined $value;
if ($key eq 'list') { $list = $value; }
elsif ($key eq 'email') { $email = $value; }
elsif ($key eq 'sub') { $subls = $value; }
elsif ($key eq 'return') {
$return = $cols->{$value}
if defined $cols->{$value};
}
else { die "invalid key: $key\n"; }
}
my $file = 'input.txt';
open FH, '<', $file
or die "Could not open '$file' $!\n";
my %emails = map { (split /\s*\t\s*/)[$return] => 'tacos' }
grep m/^${list}\s*\t\s*${email}(\s*\t\s*${subls})?\s*$/gi,
<FH>;
close FH;
return (join ', ', keys %emails);
}
print get_list(@ARGV);
print "\n";
# test input... three columns delimited by at least one tab
# third column may be blank. nothing should contain spaces
# in real life, but i'm allowing it...
# archive [email protected] success
# archive [email protected] fail
# archive [email protected] success
# archive [email protected]
# archive [email protected] fail
# taco [email protected] success
# taco [email protected] fail
# taco [email protected] success
# taco meat [email protected]
# tacor [email protected] fail
I realize some people may not be down with the $thing = $value if defined $value;
arrangement but I went ahead and used it since the logic wasn't complex. I prefer it over using space for brackets on one line conditionals. Also, please note, I'm not trying to validate email addresses with regex and I these are truly the only characters the strings will contain.
for the future person... this is what I ended up with:
#!/bin/perl
use warnings;
use strict;
sub get_list {
my $file = 'input.txt';
my %emails;
my $cols = {'list'=>0, 'email'=>1, 'sub'=>2, 'subls'=>2};
my $index = $cols->{'email'};
my $dlmtr = qr{\s*\t\s*};
my $list = qr{[a-z0-9_\- ]+};
my $email = qr{[a-z0-9@\._\-]+};
my $subls = qr{[a-z0-9\. ]+};
foreach (@ARGV) {
my ($key, $value) = split qr{=};
$value //= qr{};
if ($key eq 'list') { $list = $value; }
elsif ($key eq 'email') { $email = $value; }
elsif ($key eq 'sub') { $subls = $value; }
elsif ($key eq 'return' && defined $cols->{$value}) {
$index = $cols->{$value};
}
else { die "invalid key: $key\n"; }
}
open FH, '<', $file or die "Could not open '$file' $!\n";
while (<FH>) {
chomp;
# i couldn't get the syntax in the accept answer to parse for me
# so i changed it to this... also, %emails is better as a hash
# b/c it prevents emails added multiple times... and for my thing,
# the first two columns are required but the third may be blank.
if (m/^${list}${dlmtr}${email}(${dlmtr}(${subls}))?\s*$/gi) {
my $value = (split $dlmtr)[$index];
$value //= q{};
$emails{ $value } = 'tacos';
}
}
close FH;
return join ' ', keys %emails;
}
$value = q{} if not defined $value;
=>$value //= '';
\$\endgroup\$split /=/
to make more obvious that argument is regex. \$\endgroup\$//=
operator. That's kind of cool. \$\endgroup\$