重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

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

./log.dat に以下のように数行のログが記録されています。
文字列a<>ipアドレスa
文字列b<>ipアドレスb
文字列c<>ipアドレスc

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

A 回答 (6件)

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]";
でいいと思います。
    • good
    • 0

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++;
}

です
    • good
    • 0
この回答へのお礼

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

お礼日時:2007/03/02 00:25

以下のコードは見やすくするためスペースに全角スペースを使ってますから、コピーするなら注意してください。



(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){
  ### 処理 ###
}
    • good
    • 0
この回答へのお礼

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

お礼日時:2007/03/02 00:24

こんにちは



ちょっと頭がこんがらがってますが・・・どちらが欲しいのでしょう?

一致したとき  => 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
    • good
    • 0

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="パターンを調べるもの(この場合ログ内容)"; です

この回答への補足

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

補足日時:2007/02/27 00:48
    • good
    • 0
この回答へのお礼

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

お礼日時:2007/02/27 00:38

特定の文字列を含む行に対して処理を施したいということなのかな、と読み取りました。


こんな感じでどうでしょう。


open(IN, './logdat');
@l=<IN>;
close(IN);

$word = "文字列b<>ipアドレスb";
foreach(@l){
  if(/$word/){
    ### 処理 ###
  }
}

参考URL:http://www.tohoho-web.com/wwwperl.htm

この回答への補足

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

補足日時:2007/02/27 00:48
    • good
    • 0
この回答へのお礼

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

お礼日時:2007/02/27 00:36

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