• ベストアンサー

ファイルから文字列を読み出して、比較する方法

./log.dat に以下のように数行のログが記録されています。 文字列a<>ipアドレスa 文字列b<>ipアドレスb 文字列c<>ipアドレスc 上記ログ内に$wordに指定された文字列が含まれている場合の処理を行いたいのですが、この場合はどのように書けばよろしいのでしょうか。 $word = "文字列b<>ipアドレスb"; if ($word !~ ログ内容) {処理} ↑のように色々試してみましたがうまくいきません。Perlの知識は素人並みです。宜しくお願いいたします。

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

  • ベストアンサー
回答No.5

No.4のコメント、訂正です # $bufにファイルの中身を全部入れる ↓ # $logにファイルの中身を全部入れる それからNo.2/3さん、やはり混乱されているからでしょうか。 差し出がましいようですが、訂正が入らないと質問者さんが困惑されると思いましたので……。 > # ログの数を取得します(修正部) > $log=split(/\n/,@log); 前で > @log=<IN>; とされてますので、行数は $#log + 1 で得られます。 また現状では $log にはログ行数とは違う値が入ってしまってます。 さらに、 > foreach(@log) { > for(1..$log){ > $word="$log[$i]"; 2重ループにする必要が無く、 foreach(@log) { $word=$_; か、 for(0..$#log){ $word="$log[$i]"; でいいと思います。

その他の回答 (5)

  • leap_day
  • ベストアンサー率60% (338/561)
回答No.6

laundryload様、ご指摘ありがとうございます 確かめてみたところ確かに $log=split(/\n/,@log);は『1』でした(><) それに a文字列a<>ipアドレスa<>kk 文字列aa<>ipアドレスa<>kk 文字列a<>aipアドレスa<>kk 文字列a<>ipアドレスaa<>kk とすると 文字列a<>ipアドレスaa<>kk が一致するになってしまいました ですのでまた修正してみました open(IN,"./log.dat"); @log=<IN>; close(IN); $log= $#log; for(0..$log){ @l=split(/<>/,"$log[$j]"); $word="$l[0]"; if($word=~ /^文字列a$/) { $word="$l[1]"; if($word=~/^ipアドレスa$/) { print "一致するもの:$log[$i]<br>\n"; }else{ print "一致しないもの:$log[$i]<br>\n"; } } $i++; } 文字列a<>ipアドレスa<>kkのような形ではなく、質問のように 文字列a<>ipアドレスa だけであるなら for(0..$log){ $word="$log[$i]"; if($word=~ /^文字列a<>ipアドレスa$/) { print "一致するもの:$log[$i]<br>\n"; }else{ print "一致しないもの:$log[$i]<br>\n"; } } $i++; } です

yasainet
質問者

お礼

回答有難うございます。皆様のご親切なご指導のおかげで、解決することができました。

回答No.4

以下のコードは見やすくするためスペースに全角スペースを使ってますから、コピーするなら注意してください。 (1) やたら大きなログでないのなら $f='./logdat'; open(IN, $f); read(IN, $log, -s $f);  # $bufにファイルの中身を全部入れる close(IN); $word = "文字列b<>ipアドレスb"; if($log =~ /$word/s){  # $bufの中身を一行とみなして$wordでサーチ   ### 処理 ### } (2)ログの行数が相当多くなりそうなとき open(IN, './logdat'); @l=<IN>; close(IN); $word = "文字列b<>ipアドレスb"; $exist = 0;  # 最初 $exist は FALSE foreach(@l){   if(/$word/){     $exist = 1; # 見つかったら $exist を TRUE に     last;   } } if($exist){   ### 処理 ### } ただひとつ申しますと、質問に沿ってこのように書いてますが今のままだと、$wordとして"文字列b<>ipアドレスb"を選んだ場合  "aaa文字列b<>ipアドレスb" や  "文字列b<>ipアドレスbxxx" も一致してしまいます。 これが質問者さんの意図と違うのであれば、以下のように変えるのがいいのかな、と思います。 (1) $f = './logdat'; open(IN, $f); read(IN, $log, -s $f); close(IN); $log = "\n" . $log . "\n";  # 先頭と末尾に改行を追加 $word = "文字列b<>ipアドレスb"; if($log =~ /\n$word\n/s){  # $wordを改行で挟んでサーチ   ### 処理 ### } (2) open(IN, './logdat'); @l=<IN>; close(IN); $word = "文字列b<>ipアドレスb"; $exist = 0; foreach(@l){   if(/^$word$/){ "^"は行頭にマッチ、"$"は行末にマッチ     $exist = 1;     last;   } } if($exist){   ### 処理 ### }

yasainet
質問者

お礼

回答有難うございます。皆様のご親切なご指導のおかげで、解決することができました。

  • leap_day
  • ベストアンサー率60% (338/561)
回答No.3

こんにちは ちょっと頭がこんがらがってますが・・・どちらが欲しいのでしょう? 一致したとき  => if($word =~/ /) { } 一致しないとき => if($word !~/ /) { } $wordの後ろは半角スペース空けてくださいね(^^) ≪例として≫(ちょっと修正してます(--;) log.datに 文字列a<>ipアドレスa<>ad 文字列b<>ipアドレスb<>id 文字列c<>ipアドレスc<>cd 文字列a<>ipアドレスb<>ad 文字列b<>ipアドレスa<>id とあるとします open(IN,"./log.dat"); @log=<IN>; close(IN); # ログの数を取得します(修正部) $log=split(/\n/,@log); # 一致したときと一致しないときを一緒に処理します foreach(@log) { for(1..$log){ $word="$log[$i]"; if($word=~ /^文字列a<>ipアドレスa/) { print "一致するもの:$log[$i]<br>\n"; }else{ print "一致しないもの:$log[$i]<br>\n"; } $i++; } } print "<p>\n"; # 一致したときのみの処理です foreach(@log) { for(1..$log){ $word="$log[$j]"; if($word =~ /^文字列a<>ipアドレスa/) { print "一致したもの:$log[$j]<br>\n"; } $j++; } } print "<p>\n"; # 一致しないときの処理です foreach(@log) { for(1..$log){ $word="$log[$k]"; if($word !~ /^文字列a<>ipアドレスa/) { print "一致しなかったもの:$log[$k]<br>\n"; } $k++; } } 表示結果は 一致するもの:文字列a<>ipアドレスa<>ad 一致しないもの:文字列b<>ipアドレスb<>id 一致しないもの:文字列c<>ipアドレスc<>cd 一致しないもの:文字列a<>ipアドレスb<>ad 一致しないもの:文字列b<>ipアドレスa<>id 一致したもの:文字列a<>ipアドレスa<>ad 一致しなかったもの:文字列b<>ipアドレスb<>id 一致しなかったもの:文字列c<>ipアドレスc<>cd 一致しなかったもの:文字列a<>ipアドレスb<>ad 一致しなかったもの:文字列b<>ipアドレスa<>id となります

参考URL:
http://www.kent-web.com/perl/chap7.html
  • leap_day
  • ベストアンサー率60% (338/561)
回答No.2

open(IN,"./log.dat"); @log=<IN>; close(IN); $log=@log; # log数を取得(繰り返す回数) foreach(@log) { for(1..$log){ #繰り返す回数を指定 $word="$log[$i]"; # logを1行ずつ見ます if($word=~ /文字列c<>ipアドレスc/) { # パターンがあるか調べてます print "$log[$i]\n"; # logをHTML書き出してます } $i++; } } #以降は説明ですのであっても機能しますが邪魔なら削除してください ちなみにif ($word !~ /パターン/) は一致しなかったときの処理で $word="パターンを調べるもの(この場合ログ内容)"; です

yasainet
質問者

お礼

回答有難うございます。 申し訳ありません、質問の仕方が間違えていました。 ./log.dat内に「文字列b<>ipアドレスb」の文字列が含まれていた場合に{処理}を行いたいと考えています。 教えていただいた方法で「if($word=~ 」この部分を「if($word!~」にして試してみましたが、処理が実行されませんでした。お手数ですが、宜しくお願いいたします。

yasainet
質問者

補足

首を寝違えて痛めてしまったため、パソコンを使うことができませんでした。御礼が遅れてしまい申し訳ございませんでした。お手数ですが、引き続き宜しくお願いいたします。

回答No.1

特定の文字列を含む行に対して処理を施したいということなのかな、と読み取りました。 こんな感じでどうでしょう。 open(IN, './logdat'); @l=<IN>; close(IN); $word = "文字列b<>ipアドレスb"; foreach(@l){   if(/$word/){     ### 処理 ###   } }

参考URL:
http://www.tohoho-web.com/wwwperl.htm
yasainet
質問者

お礼

回答有難うございます。 申し訳ありません、質問の仕方が間違えていました。 ./log.dat内に「文字列b<>ipアドレスb」の文字列が含まれていた場合に{処理}を行いたいと考えています。宜しくお願いします。

yasainet
質問者

補足

首を寝違えて痛めてしまったため、パソコンを使うことができませんでした。御礼が遅れてしまい申し訳ございませんでした。お手数ですが、引き続き宜しくお願いいたします。

関連するQ&A