正規表現式の (?= ) (?: ) (?! ) の違い
正規表現式の (?=pattern) (?:pattern) (?!pattern) の違いを紹介します。
正規表現の置換で式による結果の違いを比較します。
(?=pattern) の利用
(?=pattern)を利用した正規表現式の結果を確認します。
入力 | 置換パターン | 置換文字列 | 結果 |
お店になつみかんが売れ残っていた | なつ(?=みかん) | もふもふ | お店にもふもふみかんが売れ残っていた |
お店になつすいかが売れ残っていた | なつ(?=みかん) | もふもふ | お店になつすいかが売れ残っていた |
お店になつみかんが売れ残っていた | なつ(?=りんご) | もふもふ | お店になつみかんが売れ残っていた |
お店になつみかんが売れ残っていた | なつみかん | もふもふ | お店にもふもふが売れ残っていた |
「なつ(?=みかん)」を記述した場合「なつみかん」の文字列でマッチします。ただしマッチする部分は「なつ」の文字列の部分となります。「なつすいか」はマッチの対象にはなりません。
「なつみかん」と式を記述した場合は「なつみかん」全体が置換対象となりますが(?=pattern)で記述した場合は、マッチの条件にはなりますが、マッチの範囲には含まれません。
(?:pattern) の利用
(?:pattern)を利用した正規表現式の結果を確認します。
入力 | 置換パターン | 置換文字列 | 結果 |
お店になつみかんが売れ残っていた | なつ(?:みかん) | もふもふ | お店にもふもふが売れ残っていた |
お店になつみかんが売れ残っていた | なつ(みかん) | もふもふ | お店にもふもふが売れ残っていた |
お店になつみかんが売れ残っていた | なつみかん | もふもふ | お店にもふもふが売れ残っていた |
「なつ(?:みかん)」を記述した場合、「なつみかん」の文字列でマッチします。マッチする部分も「なつみかん」全体となります。
「なつ(みかん)」と記述した場合でも同様に、「なつみかん」の文字列でマッチします。マッチする部分も「なつみかん」全体となります。
「なつみかん」と記述した場合でも同様に、「なつみかん」の文字列でマッチします。マッチする部分も「なつみかん」全体となります。
上記の3つの式は置換パターンが通常の文字列の場合は同じ結果となります。
続いてキャプチャグループを置換文字列に指定した場合の結果です。
入力 | 置換パターン | 置換文字列 | 結果 |
お店になつみかんが売れ残っていた | なつ(?:みかん) | 「$0 "$1"」 | お店に「なつみかん "$1"」が売れ残っていた |
お店になつみかんが売れ残っていた | なつ(みかん) | 「$0 "$1"」 | お店に「なつみかん "みかん"」が売れ残っていた |
お店になつみかんが売れ残っていた | なつみかん | 「$0 "$1"」 | お店に「なつみかん "$1"」が売れ残っていた |
「なつ(?:みかん)」を記述した場合、「なつみかん」の文字列でマッチします。最初のグループ$0にマッチした部分の「なつみかん」が保持されます。
「なつ(みかん)」と記述した場合も、「なつみかん」の文字列でマッチします。最初のグループ$0にはマッチした部分の「なつみかん」全体が保持されます。また、次のグループ$1には()内のパターンにマッチした「みかん」が保持されます。
「なつみかん」と記述した場合も同様に、「なつみかん」の文字列でマッチします。最初のグループ$0にマッチした部分の「なつみかん」が保持されます。
"(?:)"を記述した場合は()内でマッチしたパターンが保持されない動作になる点が異なります。
Splitでの動作の違い
グループ化の違いから、C#でRegEx.splitを利用した場合の動作も異なります。
入力 | 置換パターン | 結果 |
みかんとりんごが、お店で売っている、おいしそうです。 | 、お | みかんとりんごが 店で売っている、とても いしそうです。 |
みかんとりんごが、お店で売っている、おいしそうです。 | 、(お) | みかんとりんごが お 店で売っている、とても お いしそうです。 |
みかんとりんごが、お店で売っている、おいしそうです。 | 、(?:お) | みかんとりんごが 店で売っている、とても いしそうです。 |
みかんとりんごが、お店で売っている、おいしそうです。 | 、(?=お) | みかんとりんごが お店で売っている、とても おいしそうです。 |
()でグループ化した場合は、マッチパターンが保持されるため、()内の部分が一つの項目として分割されます。一方 (?:)でグループ化した場合は、マッチパターンが保持されないため、(?:)内の部分は一つの項目として分割されません。(?=)でグループ化した場合は(?=)のパターンはマッチ条件には含まれますがマッチ範囲には含まれないため(?=)内の文字は区切り文字として扱われません。
入力 | 置換パターン | 結果 |
広場にみかんとリンゴがたくさん入荷している。みかんは壮観な眺めだね。みかんかんかん、日照りもかんかん。 | み(かん)* | 広場に かん とリンゴがたくさん入荷している。 かん は壮観な眺めだね。 かん 、日照りもかんかん。 |
広場にみかんとリンゴがたくさん入荷している。みかんは壮観な眺めだね。みかんかんかん、日照りもかんかん。 | み(?:かん)* | 広場に とリンゴがたくさん入荷している。 は壮観な眺めだね。 、日照りもかんかん。 |
広場にみかんとリンゴがたくさん入荷している。みかんは壮観な眺めだね。みかんかんかん、日照りもかんかん。 | み(?=かん)* | 広場に かんとリンゴがたくさん入荷している。 かんは壮観な眺めだね。 かんかんかん、日照りもかんかん。 |
(?!pattern) の利用
(?!pattern)を利用した正規表現式の結果を確認します。
入力 | 置換パターン | 置換文字列 | 結果 |
お店になつみかんが売れ残っていた | なつ(?!りんご) | もふもふ | お店にもふもふみかんが売れ残っていた |
お店になつりんごが売れ残っていた | なつ(?!りんご) | もふもふ | お店になつりんごが売れ残っていた |
「なつ(?!りんご)」を記述した場合、「なつりんご」以外の「なつ~」の文字列でマッチします。「なつみかん」は「なつりんご」ではないため、マッチします。マッチの範囲には(?!patttern)は含まれないため「なつ」の部分が「もふもふ」に置換されます。入力が「なつりんご」の場合はマッチせず置換は行われません。
著者
iPentec.com の代表。ハードウェア、サーバー投資、管理などを担当。
Office 365やデータベースの記事なども担当。