自分は「 TextSS 」という置き換えソフトを使っていますが、 HTML ファイル

を対象として、以下の置き換えを行う正規表現( Perl5 )の記述を教えて
ください。

・ 「 href="リンク先" 」属性が含まれる<A>タグをコメントアウト
( <!-- ~ --> )する
・ できるなら、タグ内に半角空白と改行が含まれる場合は、記述ミスに
ならないように半角空白 1 つ( タグ内で 1 つという意味ではない )
に変換する
・ 半角空白と改行を処理する場合は、属性値内の半角空白はそのままにして、
改行は半角空白に変換する( 属性値内の扱いは、そうですよね? )

でもって、以下の条件があります

・ 属性値は、引用符( 「 " 」「 ' 」)で囲んであるとは限らない
・ 各属性間は、改行と半角スペースが複数存在する
・ 改行と半角スペースは、場所によって順序や数が同じではない
例:「 <A( 改行 )href=…省略… 」
例:「 <A( 半角空白 )( 改行 )href=…省略… 」

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2006/05/20 00:05:34
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:westfish No.4

回答回数49ベストアンサー獲得回数1

ポイント40pt

$1などで参照したくない括弧は(?:~)にするといいですよ。

今回の場合は中身を$2で参照したいわけですが、その中身の正規表現の一部に括弧が使われてしまっているためにその文字が$2に入ってしまっているわけです。ですから、「*」で繰り返されている括弧を(?:~)に変えて$2に入らないようにした上で、$2に入れる部分を改めて括弧で囲います。

<(a\s+[^>]*href[^>]*)>((?:[^<]|<(?!a))*)<(/a)>

id:watson

では、アレンジして・・・

----------------------------------------------------------------

6. <A</p>

style=color:red href=fgh style=background-color:yellow><font</p>

size=+2>fgh</font></a>

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

↓↓↓↓↓

s/<(a\s+[^>]*href=[^>]*)>((?:[^<]*|<[^\/][^>]*>|<\/[^a][^>]*>|<\/a[^>]*>)*)<(\/a)>/$2/igk

↓↓↓↓↓

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

6. <font</p>

size=+2>fgh</font>

----------------------------------------------------------------

・・・できました!!ありがとうございます m( _"_ )m

おまけに、半角空白や改行が連続していてもOKでした。

http://www.kt.rim.or.jp/~kbk/regex/regex.html#GROUPING_NOBR

自分でも、「 (?:~) 」は使えそうだと思ってたけど、説明が良く理解できませんでした

なので、「 その中身の正規表現の一部に括弧が使われてしまっているために 」の意味を完璧に理解できなくて結果オーライでした。

完璧に理解できれば、自在に扱えそうです。

あとは、コメントやスクリプトなどの中は無視する表現を付け加えることができたら完璧ですが、頭の中が崩壊すると思うので・・・( ̄∇ ̄;)ハッハッハ

改行と半角空白の圧縮は、ひょっとしたら自分でできそうです。

できなかったら、あらためて質問するかもしれませんが・・・。

長々とお付き合いいただき、ありがとうございました。 m( _"_ )m

2006/05/19 18:52:30

その他の回答3件)

id:westfish No.1

回答回数49ベストアンサー獲得回数1

ポイント10pt

http://www.din.or.jp/~ohzaki/regex.htm

最初の項目は

s/(<a [^>]*href[^>]*>)//ig

ですかね。

2つめ、3つめの質問は意味が少しわからなかったのですが…「 href="リンク先" 」の「リンク先」というのはもしかして特定のリンク先でしょうか?

id:watson

> 2 つめ、 3 つめの質問は意味が少しわからなかったのですが…

改行は半角空白として認識されて、半角空白の連続は半角空白 1 つとし

て認識されますよね

ただし、属性値内での半角空白の連続は、( 引用符で囲んであれば )その

まま認識されますよね

その認識される状態に、置き換えしたいのです

>「 href="リンク先" 」の「 リンク先 」というのはもしかして特定の

リンク先でしょうか?

単に、「 href 」属性が含まれるタグという意味です

」などは、対象外です

ところで正規表現を拝見しましたが、「 ^ 」は「 行頭 」ですよね

タグは、行の途中で始まって、行の途中で終わっている場合もあります

それと、コメントアウトのための「 !-- 」と「 -- 」の付加が無いみた

いですが・・・

よろしくお願いします

2006/05/14 19:08:49
id:westfish No.2

回答回数49ベストアンサー獲得回数1

id:watson

最初に・・・大きなヒントをもらったおかげで、ここまでできました。

感謝感激です!!

s/<(a[\s|\n]+[^>]*href=[^>]*)>([^<]*)<(\/a)>/$2/igk

置き換えしない部分の、チェンジ?での記述が解らなかったのです。

置き換えであるか否かは関係なくても、「 ( ~ ) 」の中を「 $n 」でチェンジに持っていけるのですよね。

ひょっとして、「 $1 」~「 $9 」までかな??。

それと、たとえば「 [^A]* 」は、「 A を含まない任意の文字列 」の「ゼロ回以上の繰り返し 」という理解で良いのですよね?。

「 Aではない一文字 」だと勘違いしてました。

あと、終了タグである</a>のコメントアウトを、質問に付け加えるのを忘れていました。

s/<(a[\s|\n]+[^>]*href=[^>]*)>([^<]*)<(\/a)>/$2/igk

それでですね、「 >([^<]*)< 」の部分が問題です。

これだと、タグの中に別のタグが含まれるとマッチしないのです。

以外の任意の文字列 」の「 ゼロ回以上の繰り返し 」

という表現に変更する必要があります。

「 [</a>]* 」だと、「<」「/」「A」「>」がいずれも含まれない任意の…ですよね?。

ついでなので、テスト用のHTMLファイルを紹介しておきます。

他のタグ無し)http://sub.ymwatson.com/hatena/seikihyougen_test_1.htm

他のタグあり)http://sub.ymwatson.com/hatena/seikihyougen_test_2.htm

ところで、「 \s 」は「 空白文字 」であることが解ったけど、半角と全角は同一視ですかね?

それとも、全角の空白文字は空白文字としての認識が無くて、結果的に半角空白のみが対象??

> 引用符で囲われていない属性値に空白や改行が含まれていると…省略…

> …省略…すべて単独の空白文字に変換する」ということでしょうか?

その通りです!!

内容によってはソースが見づらいので、何とかならないかナァと思ってました。

ただし、すべてだとファイル内が一行になってしまうので、「 < 」の直前にある改行は残す必要があります。

それと、これはこれで正規表現を分けたほうが使い勝手が良いですよね。

ただ、そうすると上記の表現を変え・・・なくても良いですけどね。

なお、一人当たりの回答上限を増やしました。

それと、URLは省略可能にしましたが、もし参考になるページが他にあれば・・・。

返事が長くなってスミマセンが、よろしくお願いします。 m( _"_ )m

2006/05/15 21:37:05
id:westfish No.3

回答回数49ベストアンサー獲得回数1

ポイント20pt

タグの中身部分を「([^<]|<(?!a))*」にしてはどうでしょう。「『<』以外もしくはaの続かない『<』」の繰り返しです。Aタグの中にAタグがあることはないだろう、と考えてこうしました。

$nは9までです。[^A]*は「『A以外の1文字』の0文字以上の繰り返し」なので結果的に「Aを含まない文字列」になります。

今回、私は下のサイトを参考にしました。「(?!」を使ったのは初めてでこちらも勉強になりました。

http://www.kt.rim.or.jp/~kbk/regex/regex.html

id:watson

> 。[^A]*は「『A以外の1文字』の0文字以上の繰り返し」なので結果的に「Aを含まない文字列」

やっと動作が解りました。

『A以外の1文字』は固定しないので、「 Aが見つかるまでの文字列にマッチ 」ということですね。

> タグの中身部分を「([^<]|<(?!a))*」にしてはどうでしょう。

パターン1. abc

パターン2. abc

1.「 ([^<]|<(?!a))* 」だと、以下のようになりました

s/<(a\s+[^>]*href=[^>]*)>([^<]|<(?!a))*<(\/a)>/$2/igk

( 「 \s 」は、改行を含むことが判明 & 全角空白は含まないことも判明 )

パターン1. c

パターン2. >

原因が、「 * 」がグループ化の外にあることかと思って、全体をグループ化すると・・・

2.「 ([^<]|(<(?!a))*) 」

パターン1. abc

パターン2. abc

つまり、「 </a> 」の「 > 」にマッチしてしまったと考えました。

でも、その手前は期待通り無置き換えということは・・・???。

「 > 」の直後~「 <\/a> 」の直前=「 $2 」だとすると、「 </a> 」はそのままマッチしてコメントアウトされるはずですよね。

かと言って、「 </a> }を含むとなると、期待通りではないにしてもコメントアウトされるはずがない。

なので、動作が解らず詰まってしまいましたが、他に色々とやってみました。

3.「 ([^<]*|<(?!a)*) 」

パターン1. abc

パターン2. abc

ということは、「 <(?!a)* 」の部分に問題ありです。

先ほどと違ってパターン2は置き換えされていないので、表現としては2.のほうが正解だと思ったけど・・・

4.「 (([^<]*)|(<(?!a)*))

結果は3.と同じになったので、やはり表現に問題ありでしょうか???

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

最初に考えた「 </a>を含まない文字列のゼロ回以上の繰り返し 」の発想を変えて再挑戦してみました。

・ 「 [^<]* 」=タグではない文字列

・ 「 <[^\/][^>]*> 」=「 < 」で始まるが次は「 / 」以外のタグ=終了タグではないタグ(開始タグ)

・ 「 <\/[^a][^>]*> 」=「 タグではない終了タグ

・ 「 <\/a[^>]*> 」=「 </a> 」以外のタグ=</a>タグではない終了タグ(ただしAで始まる)

これらすべてがマッチしないなら、「 > 」~「 </a> 」の間は何も無いことになりますよね?

( とりあえず改行と空白の存在は無視 )

なので、これらをor検索である「 | 」で繋げば良いと考えて、「 * 」や「 (~) 」の位置をアレンジしながら、いくつか試したけど・・・

s/<(a\s+[^>]*href=[^>]*)>([^<]*|<[^\/][^>]*>|<\/[^a][^>]*>|<\/a[^>]*>)<(\/a)>/$2/igk

パターン1. abc

パターン2. abc

ほとんどは、この結果になりました。

考え方は正しいと思うので、どうすれば良いのか解らず本格的に詰まりました。

(;´д`)トホホ

ただし、これでマッチしたとしても、or検索はマッチしたところで終わるので、「 </a> 」まで行き着かない可能性があると考えています。

アッ、行き着かないからマッチしない?!!!

そうだとすると、マッチしても検索が終わらず、かつ、最初からor検索してくれる表現があれば解決しそうですね。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

まあ、開始タグさえコメントアウトできれば、終了タグは放置しても問題ないので、とりあえず解決ということにしても良いかなと考えています。

ただし、コメントの中にがあると、それもコメントアウトしてしまって、コメントがそこから機能しなくなりますが・・・。

でも、マッチしても検索が終わらない表現とか、何か方法がありそうな気もするので、しばらく開けておきます。

そういえば、正規表現のMLとか質疑応答サイトがあれば、ありがたいですけどね。

2006/05/17 17:55:22
id:westfish No.4

回答回数49ベストアンサー獲得回数1ここでベストアンサー

ポイント40pt

$1などで参照したくない括弧は(?:~)にするといいですよ。

今回の場合は中身を$2で参照したいわけですが、その中身の正規表現の一部に括弧が使われてしまっているためにその文字が$2に入ってしまっているわけです。ですから、「*」で繰り返されている括弧を(?:~)に変えて$2に入らないようにした上で、$2に入れる部分を改めて括弧で囲います。

<(a\s+[^>]*href[^>]*)>((?:[^<]|<(?!a))*)<(/a)>

id:watson

では、アレンジして・・・

----------------------------------------------------------------

6. <A</p>

style=color:red href=fgh style=background-color:yellow><font</p>

size=+2>fgh</font></a>

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

↓↓↓↓↓

s/<(a\s+[^>]*href=[^>]*)>((?:[^<]*|<[^\/][^>]*>|<\/[^a][^>]*>|<\/a[^>]*>)*)<(\/a)>/$2/igk

↓↓↓↓↓

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

6. <font</p>

size=+2>fgh</font>

----------------------------------------------------------------

・・・できました!!ありがとうございます m( _"_ )m

おまけに、半角空白や改行が連続していてもOKでした。

http://www.kt.rim.or.jp/~kbk/regex/regex.html#GROUPING_NOBR

自分でも、「 (?:~) 」は使えそうだと思ってたけど、説明が良く理解できませんでした

なので、「 その中身の正規表現の一部に括弧が使われてしまっているために 」の意味を完璧に理解できなくて結果オーライでした。

完璧に理解できれば、自在に扱えそうです。

あとは、コメントやスクリプトなどの中は無視する表現を付け加えることができたら完璧ですが、頭の中が崩壊すると思うので・・・( ̄∇ ̄;)ハッハッハ

改行と半角空白の圧縮は、ひょっとしたら自分でできそうです。

できなかったら、あらためて質問するかもしれませんが・・・。

長々とお付き合いいただき、ありがとうございました。 m( _"_ )m

2006/05/19 18:52:30

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません