LoginSignup
1
0

More than 1 year has passed since last update.

正規表現:曖昧なパターンはエンジンによって動作が変わる(教訓)

Last updated at Posted at 2022-09-19

検索してどういうことなのか調査してみようとしたのですが、上手に検索できませんでした…。
検索しても全然それっぽい情報が出てこない!
のでとりあえず記事にしてみます。

もし原因をご存じの方いましたらお教えいただけると嬉しいです…!

環境

  • グループ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が先頭にあった場合は末尾にもあってほしい。

…グループの外にハテナつけたときって参照はちゃんと効くのかな…?
不安に思ったのでテストしてみます。

結果

グループ1(JavaScript系)でマッチした文字列
文字列
abc文字列abc

両方にマッチした!うれしい。
しかし…

グループ2(Perl系など)でマッチした文字列
abc文字列abc

なんと、環境が変わるとマッチしなくなってしまった…!
さっきテストしたらマッチしてたのに…
(当然マッチしてると思っていたので原因がわからなくてけっこう悩みました)

書き直したパターン

パターン
((?:abc)?)文字列\1

ハテナごとまとめてグループにすることで、確実に記憶がされるようにしました。
テストしてみます。

・追記:コメント欄にもっとスマートなパターンを頂きました。
こっちの方がすっきり!(テスト結果は同じです)

パターン
(abc|)文字列\1

結果

グループ1(JavaScript系)でマッチした文字列
文字列
abc文字列abc
グループ2(Perl系など)でマッチした文字列
文字列
abc文字列abc

両方ちゃんとマッチするようになりました!
わーい!

教訓

正規表現はエンジンが変わると、細かい動作が普通に変化することがあり得る…!
文字クラスの中身が変わったりするのは知っていましたが(例:pythonではデフォルトで\dに全角数字が入る)
こういう動作の変化の仕方もあるのは盲点でした…

これからはなるべく曖昧さを排除して確実なパターンを書くように心がけます。
それと、テストする際は必ず実環境と同じエンジンでテストする!

1
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0