[Perl]抽出、出力について

このQ&Aのポイント
  • メールヘッダに対して特定の条件でプログラムを実行し、IPアドレスを抽出・出力する方法について質問します。
  • プログラムを実行すると、抽出された全てのIPアドレスが表示されますが、特定のIPアドレスのみを表示する方法を知りたいです。
  • ご助言いただければ幸いです。
回答を見る
  • ベストアンサー

[Perl]抽出、出力について

質問させていただきます。 メールヘッダに対して以下のプログラムを実行します。 ~略 $file_data_str = join("", @file_data); @received_datas = split(/Received:/, $file_data_str); @received_datas = reverse(@received_datas); foreach $sorted(@received_datas){ if(($sorted =~ /by\s\w+.abc.jp/) and ($sorted =~ /(\[\d+\.\d+\.\d+\.\d+\])/)){ $& =~ /(\d+\.\d+\.\d+\.\d+)/; $ipadd = $1; print $ipadd; print "\n"; } } } exit; すると、by\s\w+.abc.jpを含むReceived行のIPアドレスが全て抽出され、複数出力されます。(以下実行結果) 114.114.96.20 158.217.208.15 私はこの初めの"114.114.96.20"のみを出力したいのですが、どうしたらいいでしょうか? 助言のほどをお願いいたします。

  • Perl
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

114.114.96.20 158.217.208.15 この2つの違いは? 具体的、どんなものは出力したくて、どんなものは出力したくないのですか? 前回の続きだとして ・最初に見つかったものだけを出力したい → 1つ出力したところで、lastとかでループから抜ける。 出力したかどうか、何番目かを記憶する変数を用意して、1つめのときだけ出力する 等 ・( IPアドレス [IPアドレス])になっている行だけを出力したい → ifで判定する条件を、これだけがマッチするようにする ・IPアドレスが特定の範囲だったら →抜き出したIPアドレスから値を取り出し、その範囲かどうかを判定する など、目的が違えば、やり方も変わります

blitzcrank
質問者

お礼

lastをつければ一発でした。。。 なぜこんなことにきがつかなかったのか、猛省してます。 本当にお世話になりました。 ありがとうございました。

blitzcrank
質問者

補足

kmee様、続けてありがとうございます。 "初めに見つかったものだけを出力したい"、ということでした。 目的がはっきりしていませんでした、申し訳ありません。 アドバイスとおりにすこしやってみます。 ありがとうございました。

関連するQ&A

  • [Perl]foreach if 抽出

    質問させていただきます。 メールヘッダに対して以下のプログラムを実行します。 ソースコード ~略 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+\])/; ここをどうにかすればいけると思うのですが詰まってしまって… 申し訳ないですが助言をお願いします。

    • ベストアンサー
    • Perl
  • [Perl]抽出について

    再度質問させていただきます。 本当は質問などせずに自力で解決したいのですがなかなかうまくいかなくて困っています… 前回質問させていただいたとき(http://okwave.jp/qa/q7855819.html)には問題なかったのですが、事情がかわってしまい、ifの中の条件を変更しなければならなくなりました。今回はIPアドレスではなく時間抽出です。 以下のメールヘッダに対して、後述するプログラムを実行します。 Received: from ************.jp (**********.jp [158.217.43.2]) by **********.abc.jp ; Wed, 29 Feb 2012 12:17:31 Received: from ************** (localhost [127.0.0.1]) by localhost (Postfix) with SMTP ; Wed, 29 Feb 2012 12:16:23 Received: from **************.jp (***********.jp [158.217.208.11]) by ************.abc.jp ; Wed, 29 Feb 2012 12:15:54 #ここがほしい Received: from **************.jp (***********.jp [158.217.208.11]) by ************.xyz.jp ; Wed, 29 Feb 2012 12:15:14   From: ************** To: *********@***********abc.jp Subject: = ***** Date:Wed, 01 Mar 2012 21:06:24   #ここがとれてしまう . . . 本文 ~略 $file_data_str = join("", @file_data); @received_datas = split(/Received:/, $file_data_str); @received_datas = reverse(@received_datas); foreach $sorted(@received_datas){ if(($sorted =~ /abc.jp/) and ($sorted =~ /(\w+,\s+\d+\s+\w+\s+\d+\s+\d+:\d+:\d+)/)){   $new_file_name = str2time($1);   $min1 = $new_file_name / 300;   $min1_cut = int( $min1 );   print $min1_cut; last; } } } exit; まず、Received:で区切って、reverseしているのではじめの要素は、元のメールヘッダの最後のReceivedフィールドから本文まであることになります。更にIfで指定してる条件のアドレスがTo:にも出現するのでそこも判定されます。なのでプログラムを実行すると、To:のabc.jpとDateの時間にひっかかってしまい、Dateの時間情報を抽出してしまいます。 あくまで取りたいのはReceivedフィールドの中の時間情報なのですが、何かいいやり方はありませんでしょうか?ちなみに やり方としては、初めの要素を消す、shiftとか使えるかな、と考えたりもしましたがうまくいかず…、Receivedフィールドのみで判定させたいです。 ご教授願えたらと思います。よろしくお願いします。

  • Perlの文字列置換について

    質問です。文字列の置換を行いたいのですが、まずはソースから・・・ use File::Basename; use File::Copy; use File::Find; use File::Path; my @filelist = (); $inputfile='C:\Users\test.txt'; $outputfile='C:\Users\test_new.txt'; open (IN, $inputfile) or die "$!"; open (OUT, ">$outputfile") or die "$!"; while(<IN>) { $str = $_; if ($str =~ /html:text/) { $str =~ s/html:text/s:textfield/g; $str =~ s/property/name/; $str =~ s/styleClass/cssClass/; elsif($str =~ /html:textarea/) { $str =~ s/html:textarea/s:textarea/g; $str =~ s/property/name/; $str =~ s/style/cssStyle/; $str =~ s/styleClass/cssClass/; } print OUT $str; } close (IN); close(OUT); sub wanted{ push(@filelist, $File::Find::dir."/$_") unless ($_ =~ /^\.$/); } Perlプログラムで下記のソースを一括置換します。 <html:text property="xxx" styleClass="yyy"> <html:textarea property="abc" styleClass="def" style="ghi"> 目標は以下のように置換したいです <s:textfield name="xxx" cssClass="yyy"> <s:textarea name="abc" cssClass="def" cssStyle="ghi"> しかし、上記のプログラムを実行すると <s:textfield name="xxx" cssClass="yyy"> <s:textfieldarea name="abc" cssClass="def" style="ghi"> となってしまいます。 どこをどう直せばよいのかわからないので誰か教えてください。 お願い致します!!

    • ベストアンサー
    • Perl
  • Perlのキャプチャ

    プログラム #!/usr/bin/perl my $str = "abc,def,ghi"; ($a,$b,$c) = $str =~ /(.*),(.*),(.*)/; print $a,"\n"; print $b,"\n"; print $c,"\n"; 実行結果 abc def ghi このようなプログラムで ($a,$b,$c) = $str =~ /(.*),(.*),(.*)/;は それぞれ$a,$b,$cにabc,def,ghiが入ります. キャプチャしたすべてを変数に入れるならこの方法ですが, defだけが欲しいのに変数を3つ用意する必要がないと思います. 間違った表記ですが, ($b) = $str =~ /(.*),(.*),(.*)/$2/; 2つ目にキャプチャした$2が変数$bに入るような表記は出来ないのでしょうか?

  • PHPでの複数ファイル出力

    よろしくお願いします。 複数の文字列を作成し($str_abc,$str_123)、それを元にファイルを作って、画面上に「開く、保存、キャンセル」のファイル出力ウインドウを出したいと思います。 ひとつだけなら、問題なくでるのですが、以下のように二つ一度に出したい(ファイル出力ウインドウが2つ)のですが、うまく出力することが出来ません。 どのようにやったら複数のファイルを一度に出すことができるのでしょうか。 <?php $str_abc = "<html><body>abc</body></html>"; $str_123 = "<html><body>123</body></html>"; //$str_abcを元にabc.htmlをつくる $fp = fopen("abc.html", 'w'); fwrite($fp,$str_abc); $fp = fopen("abc.html",'r'); header("Content-type: application/octet-stream"); header("Content-Disposition: attachment; filename=\"abc.html\""); fpassthru($fp); //$str_123を元に123.htmlをつくる $hp = fopen("123.html", 'w'); fwrite($hp,$str_123); $hp = fopen("123.html",'r'); header("Content-type: application/octet-stream"); header("Content-Disposition: attachment; filename=\"123.html\""); fpassthru($hp); ?> よろしくお願いします。

    • 締切済み
    • PHP
  • file_get_contentsでのデータ挿入

    file_get_contentsで取得したHTMLに特定の文字列を挿入して出力したいです。 下記の実行ですと'0'が返ってきてしまいます。 どこが問題なのでしょうか? <?php $html_data = mb_convert_encoding(file_get_contents("http://www.yahoo.co.jp"),'UTF-8','auto'); $str = 'aaa'; $html_data += $str; print($html_data); ?>

    • 締切済み
    • PHP
  • Perlで2つのテキストファイルの処理する方法

    めぐみです。 tatsu99さま、以下のプログラムを親切にアドバイス頂きまして本当にありがとうございました。 追記で質問させて頂きたいことがあります。 --------------------------------------------------------------- $file_a = shift(@ARGV); $file_b = shift(@ARGV); open FHA,$file_a or die("can't open $file_a"); @data_a = (); while($line=<FHA>){ chomp($line); push @data_a,$line } close FHA; open FHB,$file_b or die("can't open $file_b"); @data_b = (); while($line=<FHB>){ chomp($line); push @data_b,$line } close FHB; foreach $da (@data_a){ printf("%s%d%d%d\n",$da,$data_b[0],$data_b[1],$data_b[2]); printf("%s%d\n",$da,$data_b[0]); printf("%s%d%d\n",$da,$data_b[1],$data_b[2]); printf("%s\n",$da); printf("%s%04d%02d%02d\n",$da,$data_b[0],$data_b[1],$data_b[2]); printf("%s%02d%02d\n", $da,$data_b[1],$data_b[2]); printf("%d%d%d%s\n",$data_b[0],$data_b[1],$data_b[2],$da); printf("%d%s\n",$data_b[0],$da); printf("%d%d%s\n",$data_b[1],$data_b[2],$da); printf("%s\n",$da); printf("%04d%02d%02d%s\n",$data_b[0],$data_b[1],$data_b[2],$da); printf("%02d%02d%s\n",$data_b[1],$data_b[2],$da); }--------------------------------------------------------- 下記のような内容を追加で出力させることは難しいでしょうか。 1.B.txtを元に下記のように数字だけのデータも追加で出力させたかったです(1行目1986,2行目3,3行目6の場合) 198636 1986 36 19860306 0306 2.A.txtを元にA.txtから下記の内容も追加で出力させたかったです(4行目以降は無視して構いません)。 1行目と2行目 2行目と3行目 3行目と1行目 2行目と1行目 1行目と3行目 3行目と2行目 以上、何卒よろしくお願いいたします。

  • ポインタで分からないことがあります。

    つい最近C言語の勉強を始め、現在ポインタの勉強をしています。 過去の質問を検索したり、サイトを見てみましたが、一人の力では解決できませんでしたので質問させていただきます。 ポインタのプログラムで、下記のプログラムについて分からないことがありました。 ――――――――――――――――――――――――――――――――― #include <stdio.h> int main (void) { char *str = "abc"; printf ("%s %d %d\n", str, &str, &(*str)); str = "日本語"; printf ("%s %d %d\n", str, &str, &(*str)); return 0; } ――――――――――――――――――――――――――――――――― このプログラムで、「char *str = "abc";」の部分でstrには abcのアドレスが入っていると思っていたのですが、 1度目の「printf ("%s %d %d\n", str, &str, &(*str));」で、 結果が「abc 1245064 4235560」となっているのを見ると 私の見解は間違っている気がします。 「char *str = "abc";」の部分では一体なにが行われているのでしょうか? また、このプログラムをコンパイルして実行した結果が、 abc 1245064 4235560 日本語 1245064 4235574 となったのですが、なぜstrのアドレスは同じなのに、 &(*str)のアドレスは異なるのでしょうか? 質問をまとめますと、以下の2つです。 1.「char *str = "abc";」の部分では一体なにが行われているのでしょうか? 2.「abc」と「日本語」のstrのアドレスは同じなのに、&(*str)のアドレスは異なるのでしょうか? 初心者ですので言葉の足らない部分があるかもしれませんが、ご教授のほどよろしくおねがいします。

  • ファイルへの書き込みができない

    ファイルへの書き込みができない 実行時エラーは表示されないのですが、ファイルへ出力されません。 コードは以下のようにしています。 よろしくお願いします。 declare FILE_HANDLE utl_file.file_type; STR varchar2(1023); begin -- 書き込みモードでファイルオープン FILE_HANDLE := UTL_FILE.FOPEN('c:\tmp','test.txt','W'); STR := 'test'; -- ファイルへ出力 UTL_FILE.PUT(FILE_HANDLE,STR); -- ファイルのクローズ -- UTL_FILE.FCLOSE(FILE_HANDLE); exception when others then dbms_output.put_line('その他エラー'); end; /

  • ディレクトリーが作成されないのは何故でしょう?

    実は、下のように記述して実行してもディレクトリーが作成されずに、その原因がわからないでいます。 <?php parse_str($_COOKIE[abc]); $dirc=$ck_data1; print $dirc; if(!file_exists($dirc)){ mkdir("$dirc"); } ?> 一応ディレクトリー名を確認するために、途中でprint $dirc;を入れて ディレクトリー名を確認しましたが、問題ないようでした。 $dircという変数を遣わないで、直接ディレクトリー名を入れると 問題なくディレクトリーは作成されます。     ↓ <?php parse_str($_COOKIE[abc]); $dirc=$ck_data1; print $dirc; if(!file_exists("test")){  //←testというディレクトリー名を直接入れると、問題なくディレクトリーが作成される。 mkdir("test"); } ?> 何とか、ディレクトリ名を変数で受けて作成したいのですが、 なぜ、変数で受けることができないのかがわかりません。 どなたか、詳しい方よろしくご指導お願いいたします。

    • ベストアンサー
    • PHP

専門家に質問してみよう