電子書籍の厳選無料作品が豊富!

質問させていただきます。
メールヘッダに対して以下のプログラムを実行します。

ソースコード

~略
my $file_data_str = join("", @file_data);
my @received_datas = split(/Received:/, $file_data_str);
my @received_datas = reverse(@received_datas);
foreach my $sorted(@received_datas){
if($sorted =~ /by\s\w+.abc.jp/){
$sorted =~ /(\[\d+\.\d+\.\d+\.\d+\])/;
print $sorted;
print "\n";
}
}
}
exit;

を実行すると以下のようにに実行結果が出てきます。

from 158.217.207.30 (114.114.96.20 [114.114.96.20])
by ************abc.jp

from ****************.jp (***************.jp [158.217.208.15])
by ***********abc.jp

私は [114.114.96.20]だけを取りだしのですがどうしたらいいでしょうか?
foreach my $sorted(@received_datas){
if($sorted =~ /by\s\w.abc.jp/){
$sorted =~ /(\[\d+\.\d+\.\d+\.\d+\])/;
ここをどうにかすればいけると思うのですが詰まってしまって…
申し訳ないですが助言をお願いします。

A 回答 (3件)

「一番最初にマッチした値を知りたい」のなら, マッチした時点でループから脱出すればいいじゃん.

この回答への補足

それに気がつかなかった私はほんとおろかでした…;;

補足日時:2012/12/22 22:15
    • good
    • 0

ifでマッチした後でも$1は有効だったかと思います。



foreach $sorted (@received_datas){
if(($sorted =~ /by\s\w+.abc.jp/)and
($sorted =~ /\[(\d+?\.\d+?\.\d+?\.\d+?)\]/)){
$ipadd = $1;
print "ip $ipadd\n";
last; #<-ループを抜ける
}
}

\d.+? は最短一致(最も短く数字だけを抜き出す)
\d.+は最長一致(最も長く数字だけを抜き出す) の違いになります。\.があるので今回の場合はなくてもいいです。

\wはハイフンは入らないですが大丈夫ですね?
    • good
    • 0
この回答へのお礼

最終的にhirotn様が書いてくれたような同じようなプログラムになりました。本当に助かりました。ありがとうございます。

\wに関しては今回は大丈夫でした。ご忠告ありがとうございます。

お礼日時:2012/12/22 22:17

この状態だと、 $sorted =~ /(\[\d+\.\d+\.\d+\.\d+\])/; は何も効果ありません。


この式は、 $sorted を対象として、 /(\[\d+\.\d+\.\d+\.\d+\])/ にマッチするかどうかの評価をします。
しかし、$sortedは検索対象に使っただけで変換はしません。そのため、print $sorted;では、元々の文章がそのまま出力されます。
正規表現中()で抽出していますが、その抽出した$1を使っていません。


$sorted自体を変更する(foreachの性質上、@recieved_datas自体も書き変わる)なら、 s/// で()の中だけ残すとか。
$sorted =~ s/.*(\[\d+\.\d+\.\d+\.\d+\]).*/$1/ ; # 前後を削除

抜き出したものだけ使いたいなら、内容が変化する前なら$1 を使うとか、$1を別な変数に代入するとか。
print $1 . "\n" ; # $1をそのまま使う
$IPaddress = $1 ; # 別な変数に代入する

この回答への補足

ご回答ありがとうございます。
質問した後、ちょこちょこいじりつつ、kmee様の回答を参考にしました。

if(($sorted =~ /by\s\w+.abc.jp/) and
 ($sorted =~ /(\[\d+\.\d+\.\d+\.\d+\])/)){
$& =~ /(\d+\.\d+\.\d+\.\d+)/;
$ipadd = $1;

print $ipadd;
print "\n";
}
}
}
exit;

最終的に”[]”このかっこがない状態で出力したいので
$& =~ /(\d+\.\d+\.\d+\.\d+)/;
をいれています。
一応結果として$&にはIPアドレスはでるのですが、初めの質問に書いたメールヘッダのそれぞれのReceivedフィールドのIPアドレスが抽出されています。(以下のように)
114.114.96.20 #ここだけほしい
158.217.208.15

上の一つだけのIPアドレスを出力するにはどうしたらいいでしょうか。
申し訳ありませんが、続けて助言お願いできませんか。

補足日時:2012/12/21 22:39
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!