

JavaでHTMLタグの開始タグ・終了タグのバリデーションチェックをしたいのですが、正規表現を理解したいです。

[code]

    (<(\\s*(?:/\\s*)?【tag name】(?:\\s*|\\s+[^>]+))(?:>|(?=<)|$(?!\\n)))
    
[/code]

こちらでタグチェックをしている参考箇所を見つけたのですが、正規表現でどういう意味なのでしょうか？  
自分でも分析していますが、なかなか理解にたどり着けません。もしアドバイスいただける方がいればよろしくお願いいたします。

* * *

追記

自分なりに解析してみています。アドバイスいただけたら幸いです。  
①  
**(** <(\s*(?:/\s*)?【tag name】(?:\s*|\s+[^>]+) **)**  
**(**?:>|(?=<)|$(?!\n)) **)**  
この太字カッコは「グループ化」でしょうか？ここをまず優先的に処理する。前タグ（）のタグ名（a）前後を分けているのでしょうか？

②  
**\\\s** *は「空白０個以上」でしょうか？

③  
(?:/\\\s*)  
ここがよくわかりません。。  
「:が１個以上でしょうか？」ただタグで:があるケースってあるのかな。。  
そして「/が必要」でしょうか？あとは「空白０個以上」でしょうか？

④  
カッコのあとの?はなんでしょうか？【tag name】の前の?です

⑤  
**(**?:\s*|\s+[^>]+ **)**  
この太字カッコは「グループ化」でしょうか？

⑥  
?:  
「コロン１文字」でしょうか？コロンがよくわからない。。

⑦  
\s*は「空白が０文字以上」でしょうか？

⑧  
|で前後いずれかの文字。`?:\\s*`か`\\s+[^>]+`

⑨  
\s+で「空白１個以上」でしょうか？

⑦  
[^>]+で「>以外の文字１個以上」でしょうか？

⑧  
**(**?:>|(?=<)|$(?!\n) **)**  
太字カッコの部分がグループ化でしょうか？

⑨  
?:コロン１文字でしょうか？

⑩  
>で「>が必要」ということでしょうか？

⑪  
?:>|(?=<)|$(?!\n)  
このパイプで「?:>」か「(?=<)」か「$(?!\n)」でしょうか？

それ以降のところもご指導いただけるとありがたいです。


CC BY-SA 4.0
2020-07-11T13:47:51.137
68494
2020-07-12T13:52:13.263
2020-07-12T12:20:59.683
40231
40231
question
java 正規表現
HTML の開始・終了タグをチェックする正規表現を理解したい


こんにちは、こちらのサイトに正規表現をコピペして解析結果を読んでみるといいと思います

<https://regexr.com/>

雰囲気英語が読めればそのまま理解できると思いますが

**<**
へのマッチの後の、最初の開きカッコでは空白類を許可しています、次の開きカッコでは閉じたぐ開きタグ両方を認識するためにマッチした後、また空白類を許可しています。そのあとはタグ名です、三番目の開きカッコのあとは、空白類か
**>** でない文字にマッチ。四番目の開きカッコ以後は閉じ **>** を改行 **<** の前にきてないことを確認しながら探索している。

といった感じだと思います。


CC BY-SA 4.0
2020-07-12T01:33:09.923
68505
2020-07-12T01:33:09.923
37777
68494
answer


まず、あなたが記載された正規表現は、Javaの文字列リテラル中に埋め込まれた形になっているようです。Javaで文字列リテラル`"\\"`は、`\`の1文字を表していることは既にご理解いただいているものとしますが、`\`は、ここスタック・オーバーフローで使われているMarkdown記法でも意味を持つので、あなたの質問文中では`\\s`と表示されたり`\s`と表示されたりが混在しています。

以下の説明では、

  * 文字列リテラル中の表記であることを示すために必ず両側に`"`を付加しています  
(幸い今回の正規表現中には`"`は現れないので混乱はしにくいかと思っています。)

  * 文字そのものを表す部分はコード用のスタイルにせず太字にもしていません
  * メタ文字(文字そのもの以外を表す記号)はコード用スタイルにして太字にしています

ご質問の正規表現を上記のルールで整形しなおすと、こんな感じになります。

`"` **`(`** < **`(\\s*(?:`** / **`\\s*)?`** 【tag name】 **`(?:\\s*|\\s+[^`** >
**`]+))(?:`** > **`|(?=`** < **`)|$(?!\\n)))`**`"`

(変なところに隙間が空いてしまいますが、意図的な空白は置いていません。)

あなたが使われているブラウザで読みやすく表示されていれば良いのですが、文字そのものを表しているのは、< / > の3種類の文字しかありません。

それ以外の文字は全てメタ文字で、何らかの意味を表しています。Javaの正規表現中で使える全てのメタ文字については、Javaの公式ドキュメントに出てきています。(ただし、どこをどう取ってもわかりやすいとは言えないので、「わからん！」と思ってもあなたのせいではありません。他の解説記事と併用して読んでください。またJavaのバージョンにより若干変化があるかもしれません。)

[`Pattern` (Java platform SE 8
)](https://docs.oracle.com/javase/jp/8/docs/api/java/util/regex/Pattern.html)

その中から、ご質問の正規表現に使われているものを先の規則に当てはめて整形しながら列挙していきます。

`"` **`(`** _X_ **`)`**`"` _X_ 、前方参照を行う正規表現グループ

`"` **`\\s`**`"` 空白文字: `[\t\n\x0B\f\r]`

`"` _X_ **`*`**`"` _X_ 、0回以上

`"` **`(?:`** _X_ **`)`**`"` _X_ 、前方参照を行わない正規表現グループ

`"` _X_ **`?`**`"` _X_ 、1または0回

`"` _X_ **`|`** _Y_`"` _X_ または _Y_

`"` _X_ **`+`**`"` _X_ 、1回以上

`"` **`[^`** abc **`]`**`"` a、b、c以外の文字(否定)

`"` **`(?=`** _X_ **`)`**`"` _X_ 、幅ゼロの肯定先読み

`"` **`$`**`"` 行の末尾

`"` **`(?!`** _X_ **`)`**`"` _X_ 、幅ゼロの否定先読み

`"` **`\\n`**`"` 改行文字(「`\u000A`」)

  * 「前方参照」については、「キャプチャ」と言う言葉を使っている解説記事が多いようです。
  * 「幅ゼロの」「先読み」については、マッチするかどうかチェックするがチェック位置は進めないと言うことです。「正規表現 肯定先読み」なんかで検索すると、読みやすく書かれた解説記事が見つかると思います。

追記の①〜⑪については、 **`(?:`** 〜 **`)`**
を括弧と`?:`とに分けて解釈しようとしているのを修正すれば、ほぼ理解されているようですので、個別には触れません。この回答(やリンク先)を読んでみて、まだわからないことがあれば、コメント等でお知らせください。


CC BY-SA 4.0
2020-07-12T13:52:13.263
68525
2020-07-12T13:52:13.263
13972
68494
answer