我一直在搜索这个网站和其他人找到最好的方法来做我需要做的事但却无济于事。基本上我有一个带有一些名字和电子邮件地址的文本文件。每个姓名和电子邮件地址都在各自的位置。我需要获取电子邮件地址并将其打印到另一个文本文件。到目前为止,我能够打印的是“找不到电子邮件地址”的消息。有什么想法吗?谢谢!
#!/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);
答案 0 :(得分:8)
首先,始终 use strict; use warnings
。这有助于编写正确的脚本,在调试时非常有用。
另外,使用三个arg-open:
open my $fh, "<", $filename or die qq(Can't open "$filename": $!);
我将失败的原因包括在内($!
),这也是一个很好的做法。
读取文件的习惯用法(在打开的文件句柄上)是:
while (<$fh>) {
chomp;
# The line is in $_;
}
或
while (defined(my $line = <$fh>)) { chomp $line; ... }
您所做的是将一行读入$line
,并在for
循环中循环显示一个项。
(Perl有一个 context 的概念。像<$fh>
这样的运算符的行为取决于上下文。通常,使用标量变量($
sigil)强制标量上下文, @
,数组的sigil,导致列表上下文。这与PHP完全不同。)
我会重写您的代码,如:
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;
像[{1}}一样调用。 shell是你的朋友,创建可以通过管道传输的程序是很好的设计。
如果你希望对文件名进行硬编码,我们会将上面的脚本与我展示的三个arg开放结合起来:
perl script.pl <contacts.txt >emailaddresses.txt