検索してどういうことなのか調査してみようとしたのですが、上手に検索できませんでした…。
検索しても全然それっぽい情報が出てこない!
のでとりあえず記事にしてみます。
もし原因をご存じの方いましたらお教えいただけると嬉しいです…!
環境
- グループ1(JavaScript系)
- JavaScript (Firefox 104.0.2)
- JavaScript (Google Chrome 105.0.5195.127)
- グループ2(Perl系など)
- PCRE (PHP 7.3.11 & PCRE 10.32 2018-09-10: RegExr.com)
- Python 3.10 (re モジュール)
- コメントに頂いた検証:Ruby 3.1.2 (Onigmo)
- コメントに頂いた検証:CotEditor 4.3.4 (ICU)
PCREは「PCRE ライブラリは、Perl 5 と同じ文法構文を用いた 正規表現パターンマッチ処理を実装した関数群ですが、多少異なる点もあります (以下を参照ください)。現在の実装は Perl 5.005 に対応しています。 」とのことです。
参考:正規表現 (Perl 互換)
Pythonの正規表現は「Perl に見られる正規表現マッチング操作と同様のもの」とのことです。
参考:re --- 正規表現操作 — Python 3.10.6 ドキュメント
やりたかったこと
- 文字列
- abc文字列abc
のように、特定の文字列の前後に同じパターンがあった際に一緒に扱いたかった。
テストする文字列
文字列
abc文字列
文字列abc
abc文字列abc
最初の文字列
と最後のabc文字列abc
のみにマッチしてほしい!
最初書いたパターン
(abc)?文字列\1
abcはあってもなくてもよくて、abcが先頭にあった場合は末尾にもあってほしい。
…グループの外にハテナつけたときって参照はちゃんと効くのかな…?
不安に思ったのでテストしてみます。
結果
文字列
abc文字列abc
両方にマッチした!うれしい。
しかし…
abc文字列abc
なんと、環境が変わるとマッチしなくなってしまった…!
さっきテストしたらマッチしてたのに…
(当然マッチしてると思っていたので原因がわからなくてけっこう悩みました)
書き直したパターン
((?:abc)?)文字列\1
ハテナごとまとめてグループにすることで、確実に記憶がされるようにしました。
テストしてみます。
・追記:コメント欄にもっとスマートなパターンを頂きました。
こっちの方がすっきり!(テスト結果は同じです)
(abc|)文字列\1
結果
文字列
abc文字列abc
文字列
abc文字列abc
両方ちゃんとマッチするようになりました!
わーい!
教訓
正規表現はエンジンが変わると、細かい動作が普通に変化することがあり得る…!
文字クラスの中身が変わったりするのは知っていましたが(例:pythonではデフォルトで\d
に全角数字が入る)
こういう動作の変化の仕方もあるのは盲点でした…
これからはなるべく曖昧さを排除して確実なパターンを書くように心がけます。
それと、テストする際は必ず実環境と同じエンジンでテストする!