Perlでファイル一気読み後の正規表現で問題が発生しています

このQ&Aのポイント
  • Perlでファイル一気読み後に正規表現を当てる際、一部の箇所ではうまくいかない問題が発生しています。
  • ファイルの先頭の方では正規表現が正常に動作する一方、後半の箇所では正規表現がマッチしないことがあります。
  • 問題の原因や他の解決方法について、ご存知の方は教えていただけないでしょうか。PC環境はWindows 7で、Perlのバージョンは5.12です。
回答を見る
  • ベストアンサー

Perl ファイル一気読み後の正規表現について

Perlで以下の通り、 htmlファイルを全て読み込んだ後に正規表現を当てたいのですが、うまくいきません。 恐縮ですが、原因をご存知の方いらっしゃいましたら教えて頂けませんでしょうか。 また、他に良い解決方法がありましたら教えて頂けると幸いです。 ※PC環境はwindows7, perl5.12です。情報に不足がございましたらご指摘下さい。 ----- #--test.html(左側の数字は行数) 000001 <dl> 000002 <dt>aaa</dt> 000003 <dd>12345</dd> 000004 </dl> (中略) 120001 <dl> 120002 <dt>bbb</dt> 120003 <dd>6789</dd> 120004 </dl> #--test.pl open IN , "test.html"; local $/ = undef; $data = <IN>; close IN; $data =~ s|<td>bbb</td>|<td>ccc</td>|; print "$data\n"; ----- ファイルの始めの方だと当たるのに、後半では当たりません。 正規表現の対象として大きすぎるんでしょうか・・・。 $data =~ s|<td>aaa</td>|<td>ccc</td>|; は、当たりますが $data =~ s|<td>bbb</td>|<td>ccc</td>|; だと当たりません。 どうぞよろしくお願いいたします。

  • Perl
  • 回答数4
  • ありがとう数2

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

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

参考までに、ideoneでの実行; http://www.ideone.com/lziei 質問文の例は普通に動いてるので、SJIS変換してるあたりに原因があるかも。ないかも。

wcs_abe
質問者

お礼

お礼遅くなり申し訳ございません。 ご確認頂きありがとうございました。 (ideone.com 知りませんでした、こんなサイトがあるんですね) ちょっと時間がとれなくて細かい検証はできていないんですが、 仰る通りどうやらSjis.pmが悪さしていたようです。

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

確認ですが, この例で 1行ずつ処理したときには想定した通りの結果になっている のですね?

wcs_abe
質問者

補足

ご質問頂きありがとうございます。 はい while(<>) で処理した場合は想定通りの結果になります。 ただ一点補足がございます。 上記の質問では、関連は薄いと思いあえて記載しなかったんですが、 このhtmlファイルはSjisテキストで、それをSjis.pmを使って処理を行おうとしています。 通常のエンコードした場合で試していなかったので ちょっと後で試してみようと思います。

  • axel_eye
  • ベストアンサー率64% (145/226)
回答No.2

open IN , "test.html"; my $data; { local $/ = undef; $data = <IN>; } close IN; でスコープに入れてはどうでしょう。$/ undefしたままで他の処理を行おうとすると予期せぬ結果になるかもしれません。

wcs_abe
質問者

お礼

ご回答頂きありがとうございます。 スコープ試してみて結果は変わらなかったんですが、 そもそもスコープに入れる発想が無かったので勉強になりました。 ありがとうございました。

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

td? dt?

wcs_abe
質問者

補足

大変失礼しました。 正規表現中の "td" は "dt" の間違いです。 ご指摘頂きありがとうございました。

関連するQ&A

  • Perlの正規表現について

    Perlの正規表現について質問です. ■質問 aaa bbb aaa bbb ccc "ddd" aaa bbb ccc "ddd eee" aaa bbb ccc ddd eee "fff ggg hhh iii" というような,文字列が書かれているファイルがあるとします. ※ダブルクォーテーションが無い行もあります. ※ダブルクォーテーション内のスペースの数は,行によってそれぞれ異なります. これを,ダブルクォーテーションの中にあるスペースだけ アンダーバーに置換する場合の正規表現を教えて下さい. つまり,下記の出力にしたいです. aaa bbb aaa bbb ccc "ddd" aaa bbb ccc "ddd_eee" aaa bbb ccc ddd eee "fff_ggg_hhh_iii" ■条件 ※ちょっと古いPerlでも動くよう,ゼロ幅肯定/否定後読((?<),(!<))は使わないでください. ※単に実現するだけなら, # cat inputfile | print -pe 'sub f(){}(shift;s/ /_/;return $_;); s/(\".*\")/&f($1)/e;' みたいな感じで置換できそうですが,「正規表現だけで簡単に書けるかどうか」が知りたいのです(正規表現だけで実現出来る場合,そのアルゴリズムを知りたいです).そのため,関数と/eオプションは使わないでください.

    • ベストアンサー
    • Perl
  • 正規表現について2

    すみません、前回「正規表現について」でお世話になりました者です。 前回の分は解決したのですが、それに関連してもう少し教えてください。 data.txt---------------------------------------- aaabbbccc aaadddccc aaaeeeccc ------------------------------------------------ test.pl----------------------------------------- #!C:\Perl\bin\perl use CGI; my $q = CGI->new; $q->charset('Shift_JIS'); print $q->header(-type => "text/html"); my $line=0; open(IN,"<data.txt"); open(OUT,">output.txt"); while(<IN>){ if ($line++==0){ $output1="$1" if/aaa(.*?)ccc/;} s/aaa(.*)ccc/$1/ if (?aaa(.*)ccc?); print OUT; } close(OUT); close(IN); print $output1; ------------------------------------------------ とすることで、得られたい結果である、 output.txt-------------------------------------- bbb aaadddccc aaaeeeccc ------------------------------------------------ IEでの表示-------------------------------------- bbb ------------------------------------------------ となりました。そこで今回教えていただきたいのは、 data.txt---------------------------------------- <空行> aaabbbccc aaadddccc aaaeeeccc ------------------------------------------------ というようにdata.txtのはじめが空行の場合にも、 上記と同じような結果を得たいです。output.txtの はじめは空行になっても構いません。得られる文字として、上と同じ結果がほしいです。どうしたらよいでしょうか?よろしくお願いします。

    • ベストアンサー
    • Perl
  • perlでの正規表現について教えてください。

    たとえば、 $A = 'aaa/bbb/ccc/ddd/eee/fff/ggg' というものがあったときにperlの正規表現でddd/のすぐ後の部分を抜き取って違う変数に入れたいのですが、それを正規表現で切り取りたいのですが、どうしたらいいかわからないです。 初歩的な質問ですが、お答えいただければ幸いです。 よろしくお願いします。

  • 正規表現について

    正規表現を使用して文字列の置換(ereg_replace)をしたいと思うのですが、 うまくいかず悩んでおります。。 以下の文字列があったとします。 【AAA】【BBB】【CCC】DDD 文字列の中から先頭から始まる【】でくくられたものだけ(【AAA】)だけ削除して、 結果を【BBB】【CCC】DDDとしたいのですが、正規表現でどのようにヒットさせればよいのか分りません。 ※【】の中にくる文字はAAAとは限りません。 お手数ですがご教授頂けますでしょうか。

    • ベストアンサー
    • PHP
  • 正規表現について

    正規表現で、最初に出てきた条件に合うものだけマッチさせて置換したく、それ以降に条件に合うものがあってもマッチさせたくないのですが、どうすればいいでしょうか? 現在、オプションはつけてないのですが、最後にマッチしたものがとりだされてしまいます。 ---------------------------------------- s/aaa(.*)ccc/$1/; ・・・・・正規表現 ---------------------------- aaabbbccc : : aaadddccc : aaaeeeccc ---------- だと、eeeに置換されるのですが、bbbに置換したいです。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • 秀丸の正規表現を使って置換

    三番目の引数が0かNULL、nullならば、以下のように秀丸で置換したいのですが、やり方がわかりません。正規表現を使って置換したいです。 abcmethod(aaa, bbb, 0, ccc)やabcmethod(aaa, bbb, null, ccc)    ↓↓↓↓↓↓ abcmethod(aaa, bbb, ccc) aaa,bbb,cccは任意の文字半角アルファベットや数値です。 abcmethod(.+,.+,.+,.+)で、検索できますが、置換の仕方がわかりません。 どうぞよろしくお願いします。

  • Perlの正規表現に関する質問です。

    Perlの正規表現に関する質問です。 下記を実行した場合、$1~・・・には下記のどの正規表現に該当する値が入るの でしょうか? sub test{ my $text = shift; pos($$text) = undef; while ( $$text =~ m{ (\s*<) ( !-+ | !-+\s*(/|//)?\s*(.*?)\s*(/|//)?\s*-+ | (/)?([!a-z0-9\-]+)\s*((?:[a-z0-9\-]+\s*=\s*[\w\-/]+|[a-z0-9\-]+\s*=\s*".*?"|[a-z0-9\-]+\s*=\s*'.*?'|\s+[^<>]{2,})*)?\s*(/)? ) (>\s*) (.*?(?=(?:<!-+ | </?[a-z0-9\-!]+\s*(?:[a-z-]+\s*=\s*[\w\-/]+|[a-z0-9\-]+\s*=\s*".*?"|[a-z0-9\-]+\s*=\s*'.*?'|\s+[^>]{2,})*)\s*(/)?>?))? }sxgi ) { ・・・ }

    • ベストアンサー
    • Perl
  • 正規表現で置換

    正規表現の書き方を忘れてしまったので、教えてくださーい。 $line に以下の1行(改行なし)が入っているとして、 <a href="/aaa.pl">aaa</a><a href="/bbb.pl">bbb</a><a href="/ccc.pl">ccc</a> href="/cgi-bin/... に変換したいのです。 <a href="/cgi-bin/aaa.pl">aaa</a><a href="/cgi-bin/bbb.pl">bbb</a><a href="/cgi-bin/ccc.pl">ccc</a> てなカンジ。 よろしくです。

    • ベストアンサー
    • Perl
  • ''で囲まれていない文字列にマッチする正規表現

    下記のような文字列($str)に対して置換を行い、 my $str = qq{ AAA = BBB - 'CCC' }; $str =~ s/★正規表現★/sprintf("DDD(%s)",$1)/xmsge ; 変換後 $str = DDD(AAA) = DDD(BBB) - 'CCC' ; を実現する★正規表現★を書きたいと思っています。  ・AAA,BBB,CCCは[\w]で構成される文字列です。 ですが、シングルクォーテーション('')で囲まれていない文字列にマッチする正規表現が書けなく困っています。 一度、シングルクォーテーションで囲まれているものも含めて全てDDD()をつけて、そのあとで、シングルクォーテーションを含むものは元に戻すことでやりたいことは実現できているのですが、1行で実現できる方法を探しています。 アドバイスよろしくお願いします。

    • ベストアンサー
    • Perl
  • 何度も出現する文字列AAのうち、3番目と4番目のAAの間にある文字列を得たい

    以下のようなHTMLから、 <tr><td>AAA<td>BBB<td>CCC<td>DDD<td>EEE<td></tr> CCC という文字列だけを取り出したいとき、Perl、または 正規表現ではどのように記述したらよいのでしょうか?? Index関数を使ってみたのですが、うまくいきませんでした。 アドバイスをよろしくお願いします。

    • ベストアンサー
    • Perl