anz blog

NSPredicate で正規表現を利用する場合、全角文字の扱いに気をつけるべし

2018-07-11 #Swift

ざっくりまとめ

  • NSPredicate で正規表現利用すると意外な挙動をする
    • 全角文字をうまく判定してくれない(半角としてあつかっている?)
  • おとなしく NSRegularExpression を使いましょう

です。

環境

  • Xcode v9.4.1
  • Swift v4.1

問題

ちょっと正規表現使って、文字列のチェックをしたいなぁ〜とおもって、
NSPredicate を使ってチェックしていたわけです。

let pattern = "^[a-z]+$"
let text = "abcde"
let predicate = NSPredicate(format: "SELF MATCHES %@", pattern)
if predicate.evaluate(with: text) {
    // something
}

こういう感じですかね。
これはこれでちゃんと動くのですけど、
textabcde(cが全角) を入れるとどうでしょう??
なんと true になるのです。。
仮に pattern を [0-9] として text を 323921(9が全角) とすると...
これも true になります。。
では固定の文字列では?とおもい pattern を (foo|bar) とし text に foo(fが全角) をいれるとやっぱりこれも true ...

もしかして全角文字は無視されて判定されている?🤔
とかおもったので、「あ」とかを text にいれると false にちゃんとなるのです...。
結果から察するに、「半角に変換可能なものは半角にして実行している(あるいは半角として扱っている)」...っていうことでしょうか

対策

NSPredicate ではなくて、 NSRegularExpression を使いましょうっていうことです。
正規表現ってきたら、NSRegularExpression こっちを脳死で選ぶぐらいでいいかと。

NSRegularExpression の存在はもちろん知っていたのだけれど....
NSPredicateでもできるんだ。しかもちょっと書き方楽だなぁ(NSRegularExpressionつかうとやりたいことの割にちょいめんどいw)
ってことで、つかってたんですけどね...

でもオプションかなんかがありそうなきがするんですよねぇ...なんとなく(見つけられなかったけど(汗))
だって、NSRegularExpression ではちゃんと期待通りに動作しているわけですから


かるくソレ関連でググると、以前から同じことを言及しているものがあるので、最近出てきたっていうわけでもなさそうですね。。
英語圏なんかはいいだろうけど、日本語記事で NSPredicate を紹介しているとこ全部にコメントして回りたい(笑)

参考

NSPredicate - Foundation | Apple Developer Documentation
Predicate Format String Syntax