user2310094
user2310094

Reputation: 131

Perl program to read from a file which contains different email IDs from different domains

Perl program to read from a file which contains different email IDs from different domains. And list the username by removing the domain part.

Example:

Input file will contain:

[email protected] 
[email protected] 
[email protected] 

The output file should look like:

The domain gmail.com contains following userid: 
abc 
The domain yahoo.com contains following userid: 
xyz 
The domain test.com contains following userid:
pqr

I tried using the code but it is only separating domain and user name, but not listing user names according to domain name.

use strict;
print "Enter the file name where emailids of different domains are present\n";
my $file=<stdin>;
open(DATA, "$file") or die ("Could not open the file\n");
while(<DATA>){
    my @field=split(/@/, "$_" );
    chomp $_;
    my $username=@field[0];
    my $domain=@field[1];
    print "The user id is $username \nThe domain name is $domain \n";
}
close (DATA); 

Upvotes: 0

Views: 256

Answers (3)

user2045980
user2045980

Reputation: 37

Try This

my $file=<stdin>;
my %hash;
open(DATA, "$file") or die ("Could not open the file\n");
while(<DATA>){ 
  chomp($_);
  my @field=split(/\@/, "$_" );
  chomp(@fields);
  push(@{$hash{$field[1]}},@field);
}
close (DATA);

you have all the domains in a hash and its user names as it value that is an array reference . you can either iterate it or use Dumper

Upvotes: 0

Julian Fondren
Julian Fondren

Reputation: 5619

To keep to the point, you want to to populate a hash of arrays instead of printing as you find the addresses:

my %domains;

while(<DATA>){
  my @field=split(/@/, "$_" );
  chomp $_;
  my $username=$field[0];
  my $domain=$field[1];
  #print "The user id is $username \nThe domain name is $domain \n";
  push @{$domains{$domain}}, $username;
}
close (DATA); 

for my $domain (sort keys %domains) {
  print "The domain gmail.com contains following userid:\n";
  print "$_\n" for sort @{$domains{$domain}};
}

And to indulge in this-is-how-I'd-do-it:

#! /usr/bin/env perl
use common::sense;
use Email::Address;
use YAML 'Dump';

die "usage: $0 <file1> [<file2> ... <fileN>]\n" unless @ARGV;
# although <> reads STDIN in the absense of @ARGV,
# which is often what you want.

my %hosts;

while (<>) {
  for (Email::Address->parse($_)) {
    push @{$hosts{$_->host}}, $_->user
  }
}

print Dump \%hosts;

Given a file named 'file', containing:

abc @gamil.com 
abd @gamil.com 
abe @gamil.com 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 

This is the usage and output:

$ perl test
usage: test <file1> [<file2> ... <fileN>]
$ perl test file
---
gamil.com:
  - abc
  - abd
  - abe
test.com:
  - pqr
  - pqs
  - pqt
yahoo.com:
  - xyz
  - xy1
  - xy2

YAML's readable and useful. Email::Address saves us trouble, now and in the future.

Upvotes: 1

mvp
mvp

Reputation: 116167

You have few mistakes in your code:

  1. You need to escape @ inside strings as \@.
  2. To define Perl array, you use @array. But to address elements in array, you need to use $: $array[0].

This means, your code should look like this:

use strict;
print "Enter the file name where emailids of different domains are present\n";
my $file=<stdin>;
open DATA, "$file" or die $!;
while (my $line = <DATA>) {
    chomp $line;
    my ($username, $domain) = split /\@/, $line;
    print "The user id is $username \nThe domain name is $domain \n";
}
close DATA;

I have simplified few things, like use $line instead of $_ to make it more clear, and to save results of split into variables right away, rather than creating extra array.

Upvotes: 0

Related Questions