• ベストアンサー

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

./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

  • 文字列の比較

    現在Cでプログラムをつくっているのですが いきずまってしまいました。 1.テキストファイルを読み込む 2.書き込みファイルを開く 3.読み込んだデータを一行読み込んで   その行の特定の文字列があれば、   特定の文字列のみ取り出し、   書き込みファイルに書く。    4.次以降の行も同じ処理をする。    5.読み込み、書き込みファイルを閉じる。 と、こんな感じのプログラムなのですが、 3の特定の文字列をどのように取り出せばいいのかわかりません。 取り出したいのが数字ならば、if文でできるのですが 文字列の場合は、どうなんでしょうか。 例えば、「MOJIRETU11」という取り出したいとき 数字と同じようにIF文を使用することは、できるのでしょうか。

  • Perlでの文字列処理について

    プログラム初心者です。 Perlで下記のような文字列処理のプログラムの書き方がわからず、質問させて頂きました。 【内容】 FILE_A.txtが「!」マークで区切られていて、「!」マークの下行の文字列をIPアドレスの右横に移動したものをFILE_B.txtに出力するという処理です。 「!」マークの下行の文字列の「name」は共通です。 -------------------------------------------- 【FILE_A.txt】 ! name abcdeLV 123.123.123.123 123.123.123.124 123.123.123.125 ! name fghijLV 10.10.10.11 10.10.10.12 10.10.10.13 10.10.10.15 10.10.10.16 ! -------------------------------------------- ↓ -------------------------------------------- 【FILE_B.txt】 123.123.123.123 abcdeLV 123.123.123.124 abcdeLV 123.123.123.125 abcdeLV 10.10.10.11 fghijLV 10.10.10.12 fghijLV 10.10.10.13 10.10.10.15 fghijLV 10.10.10.16 fghijLV -------------------------------------------- 上記のようなPerlでの処理を具体的に教えて頂ければうれしいです。 本サイトのようなものを利用するのが初めてですので、不手際があるかもしれませんが なにとぞよろしくお願いいたします。

    • ベストアンサー
    • Perl
  • 任意の文字列を検索して文字を追加する。

    マクロについてご質問します。 宜しくお願い致します。 <質問> A列…すべてのデータが入っています。 B列…検索したいデータが入っています。 C列…検索結果のデータを出力します。 過去に教わったIF関数を使用した「=IF(ISNA(MATCHを組み合わせた式)」方法ですとA列の文字とB列の文字が一致しているものは そのままC列に表示で、B列に含まれないA列の文字はC列に"その他"として出力することができました。 今回は、A列の文字とB列の文字が一致している場合は C列に文字を加え、A列B列ともに一致していない場合は そのままの表示を行いたいのですがどなたかご助言していただけると助かります。 A列   B列  C列 ------------------------ 赤   白   赤   白   緑   白組 黄       黄 緑       緑組 青       青 IF関数で行うことは可能なのでしょうか? 宜しくお願い致します。

  • 【word2010】 文字列連結演算子?について

    WORD2010で差込印刷をしています。 データ元で、項目A(文字列)ブランクの場合ブランク、項目Aがブランクでなければ項目B(文字列)と項目C(文字列)を表示させたいのですが、偽の戻り値の表記のしかたが分かりません。下記のように書くと項目B(文字列)しか戻ってきません。項目C(文字列)はどのように連結すればいいのでしょうか。演算子、「&」や「+」で連結すればいいのでしょうか? {if {MERGEFIELD 項目A} = """" {MERGEFIELD 項目B}{MERGEFIELD 項目C} } ご教授のほどよろしくお願いいたします。

  • 関数名をテキストから読み込む方法(文字列比較無し)

    C言語にて開発を行っています。 今回、テキストファイルに記述された関数名および引数を読み取り、プログラム側でこれを実行する処理を実装しようと考えています。 その際、テキストから読み込んだ文字列によって処理を振り分けることを省略したいと思っていますが方法が分からず困っています。 以下が読み取る対象のテキストファイルの例です。 @function_A;arg1;arg2 @function_B;arg1;arg2 ・・・ このとき、テキストファイルから読み取った文字列に応じた関数を実行する、というところまでは実装できています。 (読み取った文字列がfunction_Aであれば、同名の関数を実行します) 現在の実装は、以下のようなイメージです。 command = "読み取った文字列(@function_Aなど)"; if(command == "@function_A"){ function_A(arg1, arg2);} else if(command == "@function_B"){ function_B(arg1, arg2);} ・・・ しかし、この実装では関数が増えるに従って if(command == "function_X"){...}をどんどん追記していく必要があります。 今後関数の数が膨大になっていく予定なので、これを追記せずに読み込んだ文字列と同名の関数を実行できるようにしたいと思っています。 以下の様なイメージです。 function_A.cというファイルに関数function_A(arg1, arg2)を実装します。 同様にして、 function_B.cに関数function_B(arg1, arg2)を実装します。 main()内にて、 char command[] = "読み取った文字列(function_Aなど)"; command(arg1, arg2); とすることによって、function_A()関数を実行できるようにすることが目的です。 もちろん、この場合のcommandはchar型ですから、上記のような記法が不可能なことは分かっていますが、似たようなことを実装したいと思っています。 どのようにすれば実装できるのでしょうか。 今後、関数の数だけfunction_A.cのようなファイルが増え、最終的に200近くになる予定ですし、 if(command == "@function_A"){ function_A(arg1, arg2);} else if(command == "@function_B"){ function_B(arg1, arg2);} ・・・ の記述忘れによる動作不良を防ぐためにもこれを実装したいと思います。

  • 文字列の比較

    excelvbaです。(excel2003) 3個のセル(a1,b1,c1)に文字列が入っています。 このそれぞれ文字列の右8桁を比較し、 最小の文字列が入っているセルに色を付けたいのです。 調べたら、minは使えませんし、dminがありましたが、 right(range("A1").value,8)をどう扱うかが分かりません。 出来ましたら、dminでなく他の方法が在ればベターです。 宜しくお願いします。

  • 文字列の中の1文字を比較するには?

    XP,Studio.NETでC++を書いています。 文字列の中の1文字を比較したいのですがどのようにしたらいいのかわかりません。 今以下のような文字列がstring[300]に入っているとします。 「\nは改行コードです。printf("");では"から"までの文字が画面に表示されます。」 このとき、1文字ずつを取り出し、文字を比較したいのですが (iを増加) if(string[i]=='\') flag=1; //処理→次にnが来る。 if(string[i]=='"') flag=2; //処理→文字はダブルコーテーション という処理をしたいのですが、 エラー:定数が多すぎます。 エラー:定数が2行目に続いています。 と出ます。どうしたらいいのでしょうか? どなたか教えていただけると幸いです。

  • Perlでの文字列操作について

    Perlを使用しての文字列操作について教えてください。 たとえば以下のような数字とアルファベットが順に並ぶ文字列があるとします。 11A4C555D67B114B9423C アルファベットは1文字ですが、数字は何個でも連続で並びます。 この文字列を「数字アルファベット」の部分で分割し、配列に格納したいのですが、うまくいきません。 @array=('11A','4C','555D','67B','114B','9423C') どなたか教えてください。よろしくお願いいたします。

  • 列A,列Bを参照して列Cにそれに対応する文字列を表示

    列A,列B,列C 4,8,A 4,9,B 4,10,B 4,11,C 4,12,C 4,13,D 3,8,E 3,9,F 3,10,F 3,11,G 3,12,G 3,13,H 2,8,I 2,9,J 2,10,J 2,11,K 2,12,K 2,13,L 1,8,M 1,9,N 1,10,N 1,11,O 1,12,O 1,13,P 列Aに1~4,列Bに4~20の値を入れ、 列Cに、計算式で上記のような文字列を表示させたいのですが、 if関数のネストが7つまでらしく8つ以上が出来ません。 何か方法がありましたらお願いします。 =IF(AND(A2=4,B2<=08),"A" ,IF(AND(A2=4,B2<=10),"B" ,IF(AND(A2=4,B2<=12),"C" ,IF(AND(A2=4,B2>=13),"D" ,IF(AND(A2=3,B2<=08),"E" ,IF(AND(A2=3,B2<=10),"F" ,IF(AND(A2=3,B2<=12),"G" ,IF(AND(A2=3,B2>=13),"H"))))))))

  • スペースを含んだ文字列から文字列の抽出

    エクセルバージョン2007 スペースを含む文字列で、A列に文字列がある時、以下の式を組んで文字列を抽出しています。 先頭にIDの数字が有る場合は、それぞれの目的に合った文字列を抽出しています。 B1=LEFT(A1,SEARCH(" ",A1,1)-1) C1=LEFT(MID(A1,SEARCH(" ",A1,1)+1,LEN(A1)-SEARCH(" ",A1,1)),SEARCH(" ",MID(A1,SEARCH(" ",A1,1)+1,LEN(A1)-SEARCH(" ",A1,1)),1)-1) 3 3df-32654-10 CCCCHH 10 1ab-12345-00 AAABBBB この文字列の場合、B列に3と10が表示、C列に 3df-32654-10 1ab-12345-00が表示されます。 先頭に、IDの無い文字列は以下の様な構成です。 6rt-95132-00 PPPKKK この文字列の場合、B列に6rt-95132-00、C列にPPPKKKが表示されてしまい、この場合、IDの数字が無い場合はB列には表示させない又は、C列に6rt-95132-00させたいと思っています。 ご教授頂ければ幸いです。 以上、宜しくお願い致します。