プロが教える店舗&オフィスのセキュリティ対策術

<div class="center">
....
<img ... class="right" ...>
....
</div>

とあるソースをperlを使って
<div class="center">
...
<img ...>
...
</div>

というように img タグの class="right" を削除したいです。
<div class="center"> の中にあるimgタグのみ対象としたいのですが、
どうすればよいのでしょうか。
なお、<div class="center"> タグの中には複数の <img ... class="right" .. >タグがある場合もあります。

A 回答 (4件)

実際のファイルを処理するには、いろいろと難しい問題があるように思います。

次の簡単な
コードは、</div> を忘れているとダメ、複数の </div> が同じ行にあるとダメというもの
ですが、出発点ぐらいにはなると思います。

use strict;
my ($range_end, $depth, $r) = ('</div>');

while (<DATA>) {
if ($r = /<div class="center">/ .. m!$range_end!) {
s/(<img [^>]*?) ?class="right"/$1/;
$depth = 0 if $r == 1;
if ($r > 1 and /<div /) {
$range_end = 'dummy_string' unless $depth;
$depth++;
}
if ($depth and m!</div>!) {
$depth--;
$range_end = '</div>' unless $depth;
}
}
print;
}

__DATA__
<div class="center">
<img src="xxx.gif" class="right" alt=""> (削除)
</div>

<div class="other">
<img src="xxx.gif" class="right" alt=""> (そのまま)
</div>

<div class="center">
<img src="xxx.gif" class="right" alt=""> (削除)
<div class="other">
<img src="xxx.gif" class="right" alt=""> (削除)
</div>
</div>

<div class="other">
<img src="xxx.gif" class="right" alt=""> (そのまま)
<div class="center">
<img src="xxx.gif" class="right" alt=""> (削除)
</div>
</div>
    • good
    • 0
この回答へのお礼

ありがとうございます。
実はhtmlファイルを丸ごと読み込んで、正規表現で変更するという処理をこの前にしています。
ですので、できれば1行ごとの処理でなく、html丸ごとに対して変換できるような正規表現が可能であれば教えていただきたいです。
それなら </div> が1行に複数あろうが単体であろうが問題ないですよね。

お礼日時:2008/10/10 14:36

http://search.cpan.org/search?query=HTML+Parser& …
http://search.cpan.org/search?query=XML+Parser&m …
http://search.cpan.org/search?query=SGML+Parser& …

HTML::Parserのような名前をしたモジュールを使うのが正攻法だと思います。
しかし、属性を削除するために使ったことがないので具体的な手順までは分かりません。
そのため、私は正規表現で何とかしようと思い立ち、計算によって以下のコードを導き出しました:

-----
#!/usr/bin/perl

use strict;
use warnings;

my $flag;

while (<>) {
$flag and s/(<img(?= ).*?) class="right"(.*?>)/$1$2/;
$flag = 1 if /<div(?= ).*? class="center".*?>/;
undef $flag if m|</div>|;
print;
}
-----

$ ./delete.pl index.html index2.html
のように、コマンドライン引数としてtext/htmlファイルを渡すと、ご質問の処理を行った後のHTML文書を標準出力に出力します。
私の環境でテストしたところ、All tests successfulでした。
しかし即興によるコードなので動く保証はありません。参考程度にお願いします。
    • good
    • 0
この回答へのお礼

HTML::TagParser を使ってみました。
getElementsByTagName( "div" ) で div タグの一覧を取得し、
attributes で属性と指定値が class="center" となるものを選別まではできますが、
そのノードの中身全部を取得するメソッドがないみたいです。
ノードの中のテキストを取得する innerText というメソッドはありますが、img タグは取得できません。
これが取得できれば、あとは img タグの class="right" を正規表現で削除するだけなんですけどね・・・。

いただいた方法なんですけど、No.4 と同じく1行ごとの処理ではなく、
$html にHTMLのソースがすべて入っているとしたときに
どうしたらよいか教えていただけないでしょうか。

お礼日時:2008/10/10 15:57

や, 使ったことはないけど HTML の解析モジュールなんか探せばその辺に転がってるような気がする.

    • good
    • 0

div のネストを考慮するかどうかによるんだけど,


まじめにやるなら何らかのモジュールを使ってソースを解析する.
手を抜いていいなら正規表現 (じゃないけど) +α で何とかなる.
    • good
    • 0
この回答へのお礼

div のネストもあります。
何らかのモジュールって、どんなモジュールがあるのでしょうか?

お礼日時:2008/10/09 11:14

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