• ベストアンサー

ファイルからのタグの検出、文字埋め込みについて

初めて投稿致します、Perl初心者です。 ※最初は他掲示板に投稿したのですが、回答者に対する補足が付けられ なかったので、改めてこちらに投稿させて頂きます。 元の投稿は今日中に閉めたいと思います。 Perlの正規表現を勉強中の初心者です。 どう書けば良いのか、分からないので教えてください。 あるHTMLファイルがあってその中に、他ページへ遷移するアンカータグ (リンク)があるとします。 そのファイルを読み込み、リンクのパスの最後に"&cnt=1111" (もしくは"?cnt=1111")というパラメータを付加したいと思っています。 例1 <A href="../aaa/bbb/ccc.html">リンク</A> →<A href="../aaa/bbb/ccc.html?cnt=1111">リンク</A> 例2 <A href="../aaa/bbb/ ←途中で改行されているケース ccc.html?xxx=222">リンク</A> →<A href="../aaa/bbb/ ccc.html?xxx=222&cnt=1111">リンク</A> 条件 1.既にcntパラメータが設定されている場合は付加しない。 2.cnt以外に他のパラメータが設定されていることがある。 3.アンカータグ内(丁度パス記述の部分やそれ以外の)ところで改行されているケースがある。 4.同じファイルには複数のアンカータグがあるとする。 5.1行で複数のアンカータグの記述も考慮 自分としては正規表現を使用すれば簡潔に出来るのではと思っている のですが、まだ初心者で恥ずかしながら応用力がありません。 上記4に関しては、ファイルから1行づつ取得してループさせれば良しとして、 1と2に関しては冗長ですが、以下にコードを記述します。 3や5を考慮する場合はどうすれば・・・・。 宜しくお願いします。 #ファイルの内容を配列に保存 my @list = <FILE>; # 1行毎に確認 foreach my $line (@list){  if($line =~ /href=/){ $smpl = $'; if( $smpl =~ /cnt=/ ){ #既に設定済みの場合、ファイルから次行を読み込む next; } else{ print "含まれてません\n"; #「html」をKEYとして左辺と右辺に分解。 if($smpl =~ /html?/ ){ $path = $`; #ファイルパス~.htmlまで $param = $'; #ファイルパス以降 $exp = $&; #引数が設定されているかどうか if($param =~ /\\?"|\\?'/){ $l_str = $`; #引数 $r_str = $'; #それ以外 $match = $&; print "$l_str\n"; print "$r_str\n"; print "$match\n"; if($l_str){ $add = "&cnt=1111"; } else{ $add = "?cnt=1111"; } $param = $l_str.$add.$match.$r_str; print "変更後:$path$param\n"; } #アンカーの途中で改行されている場合 else{ #ファイルから次行を読み込む next; } } #<A>タグ記述途中での改行時 else{ #ファイルから次行を読み込む next; } } } }

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

  • ベストアンサー
  • moon_piyo
  • ベストアンサー率60% (88/146)
回答No.1

こんにちは とりあえず、ファイル全体を一つの長い変数に格納し、該当部分をコツコツと処理していく作戦でつくってみました。 正規表現に/sオブションをつけ、.が改行にもマッチするようになってます my $temp = join("", <FILE>); my $file = ""; while ($temp =~ m! (<a\s+href=("?).*?) # 「<a href="../aaa/bbb」 -> $1 (\?.*?)? # 「?.....」バラメータはない場合もある -> $3 (\s*\2\s*>) # 「">」 --> $4 !isx) { my($p0, $p1, $p3, $p4, $p5) = ($`, $1, $3, $4, $'); if ($p3 eq '') { # バラメータ部なしの場合 $p3 = "?cnt=1111"; } elsif ($p3 !~ /^[?&]cnt=/i) { # バラメータ部はあるが「cnt=」はない場合 $p3 .= "&cnt=1111"; } $file .= "$p0$p1$p3$p4"; $temp = $p5; } $file .= $temp; print $file;

vulcan99
質問者

お礼

回答ありがとうございます。 分かりやすくコメントも付けてくださり、理解できました。 ありがとうございました。

その他の回答 (1)

  • thatsthat
  • ベストアンサー率55% (15/27)
回答No.2

行単位処理では難しい事と、/sをつける事と。 要点は完全にかぶってしまいましたが・・・参考までにコードだけ。 s///のパターンはかなり手抜きです(汗 $/=''; $line=<FILE>; $/="\n"; $line=~s#(<A href=\".*?\.html?)(\?(?:(?!cnt=).)*)?(\">.*?</A>)#($2?"$1$2&":"$1?")."cnt=1111$3"#ges; print $line;

vulcan99
質問者

お礼

回答ありがとうございます。 正規表現を利用すると随分簡潔に書けるんですね。 示した頂いたコードを、参考書とにらめっこしながら見させて 頂いて理解することが出来ました。 ありがとうございました。

関連するQ&A

専門家に質問してみよう