- IT Tips
READ MORE
こんにちは、hachi8833です。先週のTechRacho記事「Ruby 2.4.1新機能: Onigmo正規表現の非包含演算子(?~ )をチェック」の続編です。
ここで行っている非包含演算子の単独利用は挙動を理解するための極端なケースであり、実用的な意味はありませんのでご了承ください。
「Ruby 2.4.1新機能: Onigmo正規表現の非包含演算子(?~ )をチェック」記事を作成中に以下のサンプルコードを見ていて、ふと気になった点がありました。
"うらにはにわにわにはにわにわとりがいる".match?(/(?~でも)/) #=> true
"うらにはにわにわにはにわにわとりがいる".match?(/(?~には)/) #=> true
""
は「指定の文字列を含まない部分文字列」に該当するのだろうか?そうすると非包含演算子(?~)
のみを使った#match?
はどんな文字列に対してもtrue
になってしまうのだろうか?
そうなりました。空文字列に対する#match?
でもtrue
になりました。
"".match?(/(?~でも)/) #=> true
"This is a pen".match?(/(?~でも)/) #=> true
すべてを試したわけではありませんが、#match?
の中で非包含演算子だけを使ったが最後、対象の文字列の内容にかかわらずこのようにtrue
が返ると考えられます。
そしてさらに、非包含演算子(?~)
の中を空っぽにすると、#match?
は空文字を含めて、文字列の種類を問わずfalse
になります。
"".match?(/(?~)/) #=> false
"This is a pen".match?(/(?~)/) #=> false
最初この挙動を見たときにバグかと思ってしまいましたが、上述のように空文字列""
が部分文字列に該当するのであれば、この動作は筋が通っています。
以上ざっくり仮説を立てたうえで、記事公開後の夜にOnigmoのIssue #86で聞いてみました。
その結果、上の非包含演算子の挙動はやはり正常であるとのことでした。以下に大意をメモします。
この挙動は正常です。
非包含演算子
(?~somestring)
は “”や”s”や”so”や”som”…”somestrin”にもマッチしますし、”somestring”を含まないあらゆる文字列にもマッチします。どんな文字列にも “” が含まれるので、あらゆる文字列とマッチします。
逆に空の非包含演算子(?~)
は、どんな文字列にも “” が含まれるので、どんな文字列とも決してマッチしません。非包含演算子を単独で使うのはあまり使いやすくないかもしれません。アンカーや前後の文字列(prefixやsuffix)と組み合わせて使うのがよいでしょう。
ご回答ありがとうございました ?
おかげさまで非包含演算子の挙動を飲み込めました。「空文字列""
は、空文字列を含むどんな文字列にも部分文字列として含まれる」のがポイントだったんですね。
/(?~regex)/
は、対象の文字列にかかわらず#match?
で常にtrue
になる/(?~)/
は、対象の文字列にかかわらず#match?
で常にfalse
になる/うらにわ(?~にわ)にわには/