• ベストアンサー
  • すぐに回答を!

検索するプログラム

以前も同じ内容で質問させて頂いたのですが、うまくいきません。 原因はHOSTSファイルにかかれているIPアドレスの表示が XXX.XXX.1.1 となっているのですが、ログのほうは XXX.XXX.001.001となっているのでこれが原因だと思われます。 よろしくお願いいたします。 ここから以前の質問 社内でIPアドレスの管理をしているのですが、使っていないIPアドレスを ログから検索したいのです.IPアドレスはログの11番目のフィールドに書かれて おりIPの全集合はサーバのHOSTSファイルに全て記述してあります そのとき回答されたプログラム #!/usr/local/bin/perl # 未使用IPチェックスクリプト use Time::Local; my $ptnDate = '(\d\d)(\d\d)(\d\d)\-(\d\d)';  my %chkIP; # 使用されているIPを拾う my @files = glob("ログのパス"); while (@files) {   next unless /$ptnDate\.log$/;   my $tm = timelocal(0,0,$4,$3,$2-1,$1+100);   next if $tm < time() - 90*24*60*60;       # 90日より前なら見ない   open LOG, "$_" or die $!;   while (<LOG>) {     my $ip = (split /\x20/)[11];   # \x20 はスペースのコード     $chkIP{$ip} = 1;         # 見つけたIPをチェック   }   close LOG; } # 未使用のIPを探す my %notUsed; open HOSTS, "HOSTSのパス" or die $!; while (<HOSTS>) {   next unless /^(\d+\.\d+\.\d+\.\d+)/;     $notUsed{$1} = 1 unless $chkIP{$1}; } close HOSTS; # 未使用のIPを出力する open OUT, ">not_used_ip.log" or die $!; print OUT "$_\n" for sort keys %notUsed; close OUT;

共感・応援の気持ちを伝えよう!

  • 回答数2
  • 閲覧数97
  • ありがとう数2

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

  • ベストアンサー
  • 回答No.1
  • osamuy
  • ベストアンサー率42% (1231/2878)

例えば、こんなふうにするとか。 use Time::Local; > use Socket; my $ptnDate = '(\d\d)(\d\d)(\d\d)\-(\d\d)';  my %chkIP; # 使用されているIPを拾う my @files = glob("ログのパス"); while (@files) {   next unless /$ptnDate\.log$/;   my $tm = timelocal(0,0,$4,$3,$2-1,$1+100);   next if $tm < time() - 90*24*60*60;       # 90日より前なら見ない   open LOG, "$_" or die $!;   while (<LOG>) {     my $ip = (split /\x20/)[11];   # \x20 はスペースのコード >   $ip = unpack( "H*", inet_ntoa( $ip ) );     $chkIP{$ip} = 1;         # 見つけたIPをチェック   }   close LOG; } # 未使用のIPを探す my %notUsed; open HOSTS, "HOSTSのパス" or die $!; while (<HOSTS>) {   next unless /^(\d+\.\d+\.\d+\.\d+)/;   > my $ip = unpack( "H*", inet_ntoa( $1 ) ); > $notUsed{$1} = 1 unless $chkIP{$ip}; } close HOSTS; IPv4しか考えてませんが。

共感・感謝の気持ちを伝えよう!

質問者からの補足

ご回答ありがとうございます。 上記のスクリプトでためしてみたのですが うまくいきません。 他に原因はあるでしょうか?

その他の回答 (1)

  • 回答No.2
  • osamuy
  • ベストアンサー率42% (1231/2878)

> 上記のスクリプトでためしてみたのですがうまくいきません。 ありゃ。typoしてました。 誤: inet_ntoa 正: inet_aton 基本的に、比較が正しく行われるよう、データを正規化してあげましょう。 先にあげたスクリプトでは、Socket::inet_aton()を使って、ドット形式を、4バイト・データ(にしたものをunpckして16針文字列)に直すというアプローチだったんだけど。 こんなふうに: % perl -MSocket -e 'print unpack("H*", inet_aton("10.255.128.1"))' 0aff8001

共感・感謝の気持ちを伝えよう!

質問者からの補足

ありがとうございます。 すみませんpealはほとんど初心者なもので。 上記の 誤: inet_ntoa 正: inet_aton を直すだけでよろしいのでしょうか? よろしくお願いいたします。

関連するQ&A

  • プログラムの高速化

    いつもお世話になっております.以下のプログラムをできるだけ高速化したいと思います. use warnings; use strict; my $dirname = '.'; opendir(DIR, $dirname) or die "$dirname: $!"; while (my $dir = readdir(DIR)) { next unless (-f $dir); next unless ($dir =~ /\.txt$/); open(FILE, $dir) or die "$dir: $!"; while (my $line = <FILE>) { my ($a,$b,$c,$d,$e,$f) = split( /,/ , $line ); my $name = $a.",".$b; open(NEWFILE, ">> ./out/$name.txt") or die "$dir: $!"; print NEWFILE $line; close(NEWFILE); } } close(FILE); closedir(DIR); やっていることは,ディレクトリ内のテキストファイルを読み込んでいって,splitでカンマ区切りにした,$a,$bをファイル名として下のディレクトリのoutに保存していくというものです. ファイル数が数千あり,各ファイルも数千行となるため,このソースを高速化する方法はありますでしょうか.ご回答よろしくお願いします.

    • ベストアンサー
    • Perl
  • ディレクトリ内のテキストファイルに対する同一処理

    よろしくお願いします。現在Linuxの環境でテキスト処理をしております。 ディレクトリ内にファイル名の異なった以下のような大量ファイルがあります。 a.txt 0,1,2,3,4,5,6,7 1,2,3,4,5,6,7,8 b.txt 2,3,4,5,6,7,8,9 3,4,5,6,7,8,9,10 これらのファイルをカンマでsplitし、左から2番目の数にだけ1を引き,下のディレクトリであるoutに出力させます。出力は以下のようになります。 ./out/a.txt 0,0,2,3,4,5,6,7 1,2,3,4,5,6,7,8 ./out/b.txt 2,2,4,5,6,7,8,9 3,4,5,6,7,8,9,10 そこで以下のようなPerlのプログラムを作成しました。 use strict; use warnings; my $dirname = '.'; opendir(DIR, $dirname) or die "$dirname: $!"; while (my $dir = readdir(DIR)) { next unless (-f $dir); next unless ($dir =~ /\.txt$/); print $dir, "\n"; open(FILE, $dir) or die "$dir: $!"; my @file = <FILE>; foreach $line (@file) { my ($a,$b,$c,$d,$e,$f,$g,$h) = split(/,/, $line);      my $b = $b - 1; close(FILE); } open(NEWFILE, "> ./out/$dir") or die "$dir: $!"; print NEWFILE @file; close(NEWFILE); } closedir(DIR); ですが、出力は完了するのですが、元のファイルから計算がされていません。どこがどう間違えているのかご指摘よろしくお願い申し上げます。

    • ベストアンサー
    • Perl
  • 一つのテキストファイルと複数のファイルの結合

    よろしくお願いします.ディレクトリ内の一つのテキストファイル(joint.txt)と複数のファイルの結合を行ごとに隣へ結合するプログラムを作成しています.ここで以下のプログラムを作成したのですが,うまくいかないため,誤っている部分をご指摘願えないでしょうか. my $dirname = '.'; opendir(DIR, $dirname) or die "$dirname: $!"; while (my $dir = readdir(DIR)) { next unless (-f $dir); next unless ($dir =~ /\.txt$/); open(FILE, $dir) or die "$dir: $!"; open(FILE2,"joint.txt"); my @file = <FILE>; my @file2 = <FILE2>; close(FILE); close(FILE2); foreach my $line (@file) { foreach my $line2 (@file2) { chomp $line2; $line = "$line2.",".$line"; } } open(NEWFILE, "> $dir") or die "$dir: $!"; print NEWFILE @file; print NEWFILE @file2; close(NEWFILE); } closedir(DIR);

    • ベストアンサー
    • Perl
  • 連続投票の制限

    投票cgiを設置したいのですがうまくいきません、集計を1日一回だったのを少し改造して即時集計にしました 一応動くのですが、連続投票できてしまいます。 連続投票を一定時間制限できるようにしたいのですがうまくいきません 60秒くらい間をおいてから投票できるようにできますか? ip制限もあるみたいなのですがこれも機能してないです・・・ 改善できるなら元のソースがかなり変わってもかまいません 連続投票制限だけでも機能できればと思っています。よろしくお願いします local $times = time(); sub vote{ if($FORM{id}){ my $fl=0; if(!$CK_ref){$fl=1;} else{ if(index($ENV{'HTTP_REFERER'},index.html>=0){$fl=1;} } if($fl){ $FORM{id}=~s/\n//g; my $vote = $FORM{vt2}?1:0; open(OUT,">>vote_temp.cgi"); #時間用のログファイルに書き込み print OUT "$FORM{id}<>$ENV{'REMOTE_ADDR'}<>$FORM{vt}<>$vote<>".$times."<>\n"; close(OUT); &reset_vote if $VT_RESET < $times; my(@log_lines,%pt,%pt2,%cnt,$name,$value,%CKIP); open(IN,"vote_temp.cgi"); my @log = <IN>; close(IN); if(@log){ my $cktime = $times - 60; #60秒制限 open(IN,"vote_ck_IP.cgi"); #投票した人のIPを記録したログ while(<IN>){ my @ck = split('<>'); next if $_[1] < $cktime; $CKIP{$_[0]} = $_[1]; } close(IN); foreach(@log){ chop; my @rank = split('<>'); #ID<>IP<>評価<>おすすめ<>時間\n next if $CKIP{"$rank[0]_$rank[1]"}; $pt{$rank[0].'_'.$rank[2]}++; $pt2{$rank[0]}++ if $rank[3]; $cnt{$rank[0]}++; $CKIP{"$rank[0]_$rank[1]"} = $rank[4]; } open(OUT,">vote_temp.cgi"); close(OUT); open(OUT,">vote_ck_IP.cgi"); while(($name, $value) = each(%CKIP)){ print OUT "$name<>$value<>\n"; } close(OUT); open(IN,"log.cgi"); my @data = <IN>; close(IN); foreach(@data){ #集計処理長かったので省略 } open(OUT,">vote_bf.cgi"); open(IN,"vote_log.cgi"); while(<IN>){ print OUT $_; } close(IN); close(OUT); open(OUT,">vote_log.cgi"); print OUT @log_lines; print OUT "\n1;\n"; close(OUT); } &make_vote_ck('set'); } } sub reset_vote{ my @log; foreach my $i(1..$LAST_ID){ next if !@{$VT[$i]}; $VT[$i][18] = $VT[$i][7]; $VT[$i][19] = $VT[$i][8]; $VT[$i][20] = $VT[$i][0]; foreach my $j(0..8){ $VT[$i][$j] = 0; } push(@log,'$VT['.$i.'] = ['.(join(',',@{$VT[$i]}))."];\n"); } open(OUT,">vote_log.cgi"); print OUT @log; print OUT "\n1;\n"; close(OUT); &make_vote_ck('reset'); } sub make_vote_ck{ if($_[0] eq 'set'){ my @t =localtime($times + 86400); $VT_TIME = timelocal(0,0,5,$t[3],$t[4],$t[5]); $VT_RANK = $VT_RUI = $VT_RECO = $VT_RCRUI = $VT_COUNT = $VT_CTRUI = $VRK_CK = 1; } if($_[0] eq 'reset'){ my @m =localtime($times); $m[4] += 1; if($m[4] > 12){ $m[4] = 1; $m[5] += 1; } $VT_RESET = timelocal(0,0,2,1,$m[4],$m[5]); $VT_RANK = $VT_RECO = $VRK_RS = $VRK_CK = 1; } if($_[0] eq 'restore'){ $VT_RANK = $VT_RUI = $VT_RCRUI = $VT_RECO = $VT_COUNT = $VT_CTRUI = $VRK_CK = 1; } open(OUT,">vote_ck.cgi"); print OUT "\$VT_TIME = '".$VT_TIME. "';\n"; print OUT "\$VT_RESET = '".$VT_RESET. "';\n"; print OUT "\$VT_RANK = '".$VT_RANK. "';\n"; print OUT "\$VT_RUI = '".$VT_RUI. "';\n"; print OUT "\$VT_RECO = '".$VT_RECO. "';\n"; print OUT "\$VT_RCRUI = '".$VT_RCRUI. "';\n"; print OUT "\$VT_COUNT = '".$VT_COUNT. "';\n"; print OUT "\$VT_CTRUI = '".$VT_CTRUI. "';\n"; print OUT "\$VRK_CK = '".$VRK_CK. "';\n"; print OUT "\$VRK_RS = '".$VRK_RS. "';\n"; print OUT "\$LAST_ID = '".$LAST_ID. "';\n"; print OUT "\n1;\n"; close(OUT); }

    • ベストアンサー
    • Perl
  • 下のディレクトリ(3つ)に含まれる同じファイル名のテキストを結合し,カレントディレクトリに出力する

    いつもお世話になっております.環境はWindows XPのActiveperlです. やりたいことは「下のディレクトリ(3つ)に含まれる同じファイル名のテキストを結合し,カレントディレクトリに出力する」ことです.具体的にはいかのようにしたいと思っています. 現在のディレクトリ/a/1.txt a b c 現在のディレクトリ/b/1.txt d e f 現在のディレクトリ/c/1.txt g h i 現在のディレクトリ/1.txt a b c d e f g h i ここで私は以下のプログラムを作成しました. use strict; use warnings; my $dirname1 = './a/'; my $dirname2 = './b/'; my $dirname3 = './c/'; opendir(DIR1, $dirname1) or die "$dirname1: $!"; while (my $dir1 = readdir(DIR1)) { next unless (-f $dir1); next unless ($dir1 =~ /\.txt$/); opendir(DIR2, $dirname2) or die "$dirname2: $!"; while (my $dir2 = readdir(DIR2)) { next unless (-f $dir2); next unless ($dir2 =~ /\.txt$/); opendir(DIR3, $dirname3) or die "$dirname3: $!"; while (my $dir3 = readdir(DIR3)) { next unless (-f $dir3); next unless ($dir3 =~ /\.txt$/); if (($dir1 == $dir2) && ($dir2 == $dir3)){ open(FILE1, $dir1) or die "$dir1: $!"; my $line1 = <FILE1>; close(FILE1); open(FILE2, $dir2) or die "$dir2: $!"; my $line2 = <FILE2>; close(FILE2); open(FILE3, $dir3) or die "$dir3: $!"; my $line3 = <FILE3>; close(FILE3); my $joint_line = $line1.$line2.$line3; open(NEWFILE, "> $dir1") or die "$dir1: $!"; print NEWFILE $joint_line; close(NEWFILE); } } } } closedir(DIR1); closedir(DIR2); closedir(DIR3); ですが,以下のようなエラーが発生しています. closedir() attempted on invalid dirhandle DIR2 at joint.pl line 51. closedir() attempted on invalid dirhandle DIR3 at joint.pl line 52. ディレクトリハンドルが使われているけれど閉じているか実際にはディレクトリハンドルでは無い時にこれらの警告が発行されるとこの警告がでるようですが,どのようにしたら解決できるのでしょうか.よろしくお願いします.

  • 全行読み込むには

    open( IN, "pass.dat" ) or die "Can't open pass.dat: $!"; $f_data = <IN>; close( IN ) or die "Can't close pass.dat: $!"; $f_data1 = $f_data; $f_data2 = $f_data; $f_data1 =~ s/<br>//g; $f_data2 =~ s/\S//g; open( OUT, ">log.dat" ) or die "Can't open log.dat: $!"; select OUT; print "$f_data1"; print "$f_data2"; select STDOUT; close( OUT ) or die "Can't close word.js: $!"; 上記スクリプトでは、pass.datの一行目しか読み込まれません。全行を読み込むためにはどのように書き換えればいいのでしょうか?宜しくお願いします。

    • ベストアンサー
    • Perl
  • ログファイルの指定行に書込み

    open(IN,"$log") || &error("Open Error"); @data = <IN>; close(IN); while (100 <= @data) { pop(@data); } open(OUT,">$log") || &error("Write Error"); print OUT "$in{'id'}<>$in{'comment'}\n"; print OUT @data; close(OUT); ログにはID、時間、コメントが登録されています。 送信データの中に、ログに登録済みのIDがある場合には、そのIDのある行のみを書き換えたいのですが、方法がどうしてもわかりません。 $logに記録されるIDの順番は以下のようにランダムです。IDに登録される文字列は1からの数値のみです。 52<>コメント 120<>コメント 35<>コメント 8<>コメント 2<>コメント 19<>コメント 85<>コメント よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • ログの一部を消す Perl

    ログの一部を消すPerlを考えています。 ここではソースを短くするために、ログの一部を消し去って ログファイルに上書きするデータは $deta だけだとすると open F, '+<a.log'; flock F,2; $deta = <F>;//実際はここでもっと処理 truncate F,0; seek F,0,0; print F $deta; close F; と、 open IN, 'a.log'; flock IN,2; open OUT, '>a.log'; flock OUT,2; $deta = <IN>;//実際はここでもっと処理 print OUT $deta; close OUT; close IN; の2つを考えました。 上のように 読み込み と 書き込み を同時にやった方がいいのか 下のように分けてやった方がいいのか教えてください。 ロックは flock を使って、普通レベルのロックが できるぐらいでいいと思っているんだけど、 この flock の書き方でおかしいところがあれば 教えてください。

    • ベストアンサー
    • CGI
  • perlで検索 カンマ n番目

    ~log.txt~ 1,a,w,e,r 2,a,w,e,r 2,e,a,v,ssss 3,s,ssss,a,a $FILE = 'log.txt'; $Search = 'sss'; ~Search.pl~ open(FILE, "<$FILE") or die("error :$!"); eval{ flock(FILE, 1) }; @DATA = <FILE>; close FILE; $a = 0; my @Search = grep(/$Search,/, @DATA); while (<@Search>) { $a++; } print "@Search\n"; このようなデータで 検索ワード=sssのとき ヒットするのが 2,e,a,v,ssss 3,s,ssss,a,a [0][1][2][3][4] この2つです。 ここまではいいのですが、 2番目のsssのみを取り出したいとき my @Search = grep(/$Search,/, @DATA); ここをどのように変えればいいのでしょうか・・・?

    • ベストアンサー
    • Perl
  • とあるソフトの裏の通信?について

    とあるソフトを使うと、勝手に通信を行っているようです。 そのソフト自体は正規のもので問題の無いものなので使い続けたいのですが、何となく勝手に通信がされているのは気持ち悪いので、何とかその通信を止めたいですが、やり方がわかりません。ソフトを立ち上げると、特定のIPに対して、よく分かりませんが、接続が確立されるようです。 環境は、ADSLモデム → ルーター → PC(WindowsXP)です。 hostsファイルで、127.0.0.1 ○○.○○.○○.○○ ←※そのIPです。 ・・・などとしても、hostsは無視されるみたいで、XP標準のファイアーウォールのログを取りますと、ソフトを立ち上げると、やはり、そのIPに対して、OPENが残りまして、そのソフトを閉じると、CLOSEが残ります。 パケットフィルタリングが出来るフリーソフト?みたいなのをいくつか試しまして、そのIPに対する通信は遮断・・・みたいな設定を行ってみたのですが・・・そういったソフト上では、ログはちゃんとBLOCKとかなっているんですが、 改めてWIN標準もログを見ると、やはり同じ様に、そのIPに対する、OPENとCLOSEが、一回残っていますので、どうも釈然としません。 こういった場合、そのIPに対する完全なる遮断はできないものでしょうか? 何かしら方法はありませんでしょうか。。。 レスいただけましたら幸いです。