Swiftで旧漢字を判定したかった

できなかった

  • 方針その1: shift-jisに変換できるかどうかで判別する

参考: www.softel.co.jp

extension String {
    func containsOldKanji() -> Bool {
        return !self.canBeConverted(to: .shiftJIS)
    }
}

let str = "高"
str.containsOldKanji() // true

let str2 = "髙"
str2.containsOldKanji() // なぜかtrue

後々の試行錯誤中にshift-jis変換がうまくいっていることが判明し、IBM拡張なるものを知る
f:id:slowlylearner:20180104033139p:plain
文字コード表 シフトJIS(Shift_JIS)

  • shift-jis変換は成功しているので、IBM拡張の範囲(纊~黑まで)の漢字が含まれているかどうかを判定する

結果から言うとだめ

extension String {
    func containsOldKanji() -> Bool {
        //        return !self.canBeConverted(to: .shiftJIS)
        return containsIBMExtension()
    }
    
    
    func containsIBMExtension() -> Bool {
        guard let data = self.data(using: .shiftJIS),
            let shiftJISStr = String(data: data, encoding: .shiftJIS)
            else {
                return false
        }
        
        // http://charset.7jp.net/sjis.html のIBM拡張(?)で漢字相当の範囲を引っ掛ける
        let regEx = ".*[\u{ed40}-\u{eeec}]+.*"
        let test = NSPredicate(format: "SELF MATCHES %@", regEx)
        return test.evaluate(with:shiftJISStr)

上の後でパターンの方もshiftjisにしないとだめかなーとか漢字をダイレクトにパターンに入れてしまえばいいのではないかと思ったがダメだった。

extension String {
    func containsOldKanji() -> Bool {
        //        return !self.canBeConverted(to: .shiftJIS)
        return containsIBMExtension()
    }
    
    
    func containsIBMExtension() -> Bool {
        guard let data = self.data(using: .shiftJIS),
            let shiftJISStr = String(data: data, encoding: .shiftJIS)
            else {
                return false
        }
        
        // http://charset.7jp.net/sjis.html のIBM拡張(?)で漢字相当の範囲を引っ掛ける
        let regEx = ".*[纊-黑]+.*"
        guard let dataRegEx = regEx.data(using: .shiftJIS),
            let shiftJISRegEx = String(data: dataRegEx, encoding: .shiftJIS)
            else {
                return false
        }
        
        let test = NSPredicate(format: "SELF MATCHES %@", shiftJISRegEx)
        return test.evaluate(with:shiftJISStr)

最後の方は両方ともcontainsOldKanjiがtrueを返していたので「纊-黑」の範囲がshift-jisではなくutf-16とかunicodeとかで解釈されている可能性があり、そもそも何がどうなるとswiftの時代にshift-JISで正規表現を書くのだろうかという気持ちになった。