likeで終わる単語を一致させ#
たい
こんにちはこんにちは# 世界#
境界線を使ってみた
\b\w+#\b
単語境界ではないと思っ\b
ていたのですが、今回の場合はそうではないようです
驚くべきことに
\b\w+#\B
マッチ!
では、なぜ\B
ここで機能し、機能しないのですか!また、この場合\b
は機能しないのはなぜですか!\b
注:
はい、使用できますが、この場合に機能する\b\w+#(?=\s|$)
理由を知りたいです!\B
likeで終わる単語を一致させ#
たい
こんにちはこんにちは# 世界#
境界線を使ってみた
\b\w+#\b
単語境界ではないと思っ\b
ていたのですが、今回の場合はそうではないようです
驚くべきことに
\b\w+#\B
マッチ!
では、なぜ\B
ここで機能し、機能しないのですか!また、この場合\b
は機能しないのはなぜですか!\b
注:
はい、使用できますが、この場合に機能する\b\w+#(?=\s|$)
理由を知りたいです!\B
\b
word での単語境界の定義は不正確です。先読み、後読み、略語文字クラスで単語境界を定義しましょう\w
。
単語境界\b
は次と同等です。
(?:(?<!\w)(?=\w)|(?<=\w)(?!\w))
つまり:
すぐ前には (少なくとも) 単語の文字である文字があり、すぐ後ろには単語の文字が見つかりません (文字が単語の文字ではないか、文字列の先頭です)。
また
(これが XOR の論理積と論理和への展開にいかに似ているかに注意してください)
非単語境界\B
は次と同等です。
(?:(?<!\w)(?!\w)|(?<=\w)(?=\w))
つまり:
すぐ前も後ろも、単語の文字が見つかりません。この定義では、空の文字列は非単語境界と見なされることに注意してください。
また
(これが XNOR の論理積と論理和への拡張にいかに類似しているかに注意してください)。
\w
\b
andの定義は1の定義\B
に依存するため、特定のドキュメントを参照して、何が一致するかを正確に知る必要があります。\w
\w
1正規表現フレーバーのほとんどは、に\b
基づいて定義され\w
ます。Java [Point 9]を除いて 、デフォルト モードでは ASCII のみで部分的に Unicode を認識します。\w
\b
JavaScriptでは[A-Za-z0-9_]
、デフォルト モードになります。
.NETでは、\w
デフォルトで に一致し、 ECMAScript オプション[\p{Ll}\p{Lu}\p{Lt}\p{Lo}\P{Lm}\p{Nd}\p{Pc}]
が指定されている場合は JavaScript と同じ動作になります。PCカテゴリの文字一覧では、スペース(ASCII32)が入っていないことだけは知っておいてください。
上記の定義により、質問への回答は簡単になります。
"hi hello# world#"
ではhello#
、後ろ#
はスペース ( U+0020、Zs カテゴリ) であり、単語文字で#
はなく、単語文字自体ではありません ( Unicode では、Po カテゴリにあります)。したがって、\B
ここで一致できます。この場合、ブランチ(?<!\w)(?!\w)
が使用されます。
ではworld#
、後ろ#
は文字列の終わりです。は単語文字ではなく、#
前方に単語文字を見つけることができない (そこには何もない) ため、\B
の直後の空の文字列に一致する可能性があり#
ます。(?<!\w)(?!\w)
この場合もブランチが使用されます。
Alan Moore は、コメントで非常に優れた要約を提供しています。
覚えておくべき重要な点は、正規表現は読み取れないということです。つまり、彼らは言葉ではなく、文字だけを扱います。が単語の先頭または末尾に一致すると言うとき
\b
、人間が行うように、単語を識別してからその終点を探すという意味ではありません。見えるのは、現在位置の前の文字と現在位置の後の文字だけです。したがって、\b
現在の位置が単語境界である可能性があることのみを示します。両側のキャラクターがどうあるべきかを確認するのはあなた次第です。
と#
スペースはどちらも非単語文字であるため、それらの間の目に見えない境界は単語の境界ではありません。したがって\b
、一致せず、\B
一致します。