まず、常に use strict; use warnings
. これは、正しいスクリプトを作成するのに役立ち、デバッグ時に非常に役立ちます。
また、three-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; ... }
あなたがしたことは、1 行を に読み込み$line
、ループ内のその1 つの項目をループすることfor
でした。
(Perl にはcontextの概念があります。演算子 likeは、コンテキスト<$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;
のように呼び出されperl script.pl <contacts.txt >emailaddresses.txt
ます。シェルはあなたの友人であり、パイプでやり取りできるプログラムを作成するのは良い設計です。
アップデート
ファイル名をハードコーディングしたい場合は、上記のスクリプトを、私が示した 3 つの引数の open と組み合わせます。
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