1

我一直在搜索这个网站和其他网站,以找到做我需要做的事情的最佳方法,但无济于事。基本上我有一个包含一些姓名和电子邮件地址的文本文件。每个姓名和电子邮件地址都在自己的行中。我需要获取电子邮件地址并将它们打印到另一个文本文件中。到目前为止,我能够打印的只是“未找到电子邮件地址”消息。有什么想法吗?谢谢!!

#!/usr/bin/perl

open(IN, "<contacts.txt") || die("file not found");
#chooses the file to read
open(OUT, ">emailaddresses.txt");
#prints file
$none = "No emails found!";
$line = <IN>;

for ($line)
{
    if ($line =~ /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}/g)
    {
        print (OUT $line);
    }
    else
    {
        print (OUT $none);
    }
}

close(IN);
close(OUT);
4

1 回答 1

8

First, always use strict; use warnings. This helps writing correct scripts, and is an invaluable aid when debugging.

Also, use a three-arg-open:

open my $fh, "<", $filename or die qq(Can't open "$filename": $!);

I included the reason for failure ($!), which is a good practice too.

The idiom to read files (on an open filehandle) is:

while (<$fh>) {
  chomp;
  # The line is in $_;
}

or

while (defined(my $line = <$fh>)) { chomp $line; ... }

What you did was to read one line into $line, and loop over that one item in the for loop.

(Perl has a notion of context. Operators like <$fh> behave differently depending on context. Generally, using a scalar variable ($ sigil) forces scalar context, and @, the sigil for arrays, causes list context. This is quite unlike PHP.)

I'd rewrite your code like:

use strict; use warnings;
use feature 'say';
my $regex = qr/[A-Z0-9._%+-]+\@[A-Z0-9.-]+\.[A-Z]{2,4}/i; # emails are case insensitive
my $found = 0;

while (<>) { # use special ARGV filehandle, which usually is STDIN
  while (/($regex)/g) {
    $found++;
    say $1;
  }
}
die "No emails found\n" unless $found;

Invoked like perl script.pl <contacts.txt >emailaddresses.txt. The shell is your friend, and creating programs that can be piped from and to is good design.

Update

If you want to hardcode the filenames, we would combine the above script with the three-arg open I have shown:

use strict; use warnings; use feature 'say';
use autodie; # does `... or die "Can't open $file: $!"` for me
my $regex = qr/[A-Z0-9._%+-]+\@[A-Z0-9.-]+\.[A-Z]{2,4}/i;
my $found = 0;

my $contact_file = "contacts.txt";
my $email_file   = "emailaddresses.txt";

open my $contact, "<", $contact_file;
open my $email, ">", $email_file;

while (<$contact>) {    # read from the $contact filehandle
  while (/($regex)/g) { # the /g is optional if there is max one address per line
    $found++;
    say {$email} $1;    # print to the $email file handle. {curlies} are optional.
  }
}
die "No emails found\n" unless $found; # error message goes to STDERR, not to the file
于 2013-03-29T20:00:03.383 回答