常用正則表達(dá)式 Swift 5

整理了一些常用的Swift正則表達(dá)式,包括最新的手機(jī)號(hào)驗(yàn)證,希望對(duì)小伙伴兒們有幫助。

import Foundation
import UIKit

open class Validator {
    
    // MARK: 人臉檢測(cè)
    /// 人臉檢測(cè)
    /// - Parameter image: 被檢測(cè)圖像
    /// - Returns: 是否含有人像
    public static func checkFace(_ image: UIImage) -> Bool {
        let ciimage = CIImage(cgImage: image.cgImage!)
        let detector = CIDetector(ofType: CIDetectorTypeFace,
                                  context: nil,
                                  options: [CIDetectorAccuracy: CIDetectorAccuracyLow])!
        let result = detector.features(in: ciimage)
        // 識(shí)別出的特征數(shù)量
        return result.count > 0 ? true : false
    }
    // MARK: 通用匹配
    /// 通用匹配
    /// - Parameters:
    ///   - input: 匹配的字符串
    ///   - pattern: 匹配規(guī)則
    /// - Returns: 返回匹配的結(jié)果
    public static func match(_ input: String, pattern: String) -> Bool {
        guard let regex: NSRegularExpression = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) else {
            return false
        }
        let matches = regex.matches(in: input,
                               options: [],
                                 range: NSMakeRange(0, input.utf16.count))
        return matches.count > 0
    }
    // MARK: URL驗(yàn)證
    /// URL驗(yàn)證
    /// - Parameter string: 被校驗(yàn)字符串
    /// - Returns: 驗(yàn)證結(jié)果
    ///
    ///     checkUrl("https://google.com") -> true
    ///
    public static func checkUrl(_ string: String) -> Bool {
        return URL(string: string) != nil
    }
    
    // MARK: 正則匹配用戶姓名,20位的中文或英文
    /// 用戶名驗(yàn)證
    /// - Parameter string: 被校驗(yàn)字符串
    /// - Returns: 驗(yàn)證結(jié)果
    ///
    ///     checkUserName("張三123") -> true
    ///
    public static func checkUserName(_ string: String) -> Bool {
        let regex = "^[a-zA-Z\\u4E00-\\u9FA5]{1,20}"
        let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
        return predicate.evaluate(with: string)
    }
    
    // MARK: URL Schemed 是否有效
    /// URL Schemed 是否有效
    /// - Parameter string: 被校驗(yàn)字符串
    /// - Returns: 驗(yàn)證結(jié)果
    ///
    ///     checkSchemedUrl("https://google.com") -> true
    ///     checkSchemedUrl("google.com") -> false
    public static func checkSchemedUrl(_ string: String) -> Bool {
        guard let url = URL(string: string) else { return false }
        return url.scheme != nil
    }
    
    // MARK: 郵箱驗(yàn)證
    /// 郵箱驗(yàn)證
    /// - Parameter email: 被校驗(yàn)字符串
    /// - Returns: 驗(yàn)證結(jié)果
    ///
    ///     "john@doe.com".isValidEmail -> true‘
    ///
    public static func checkEmail(_ email: String) -> Bool
    {
        let regex = "^(?:[\\p{L}0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[\\p{L}0-9!#$%\\&'*+/=?\\^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[\\p{L}0-9](?:[a-z0-9-]*[\\p{L}0-9])?\\.)+[\\p{L}0-9](?:[\\p{L}0-9-]*[\\p{L}0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[\\p{L}0-9-]*[\\p{L}0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])$"
        let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
        return predicate.evaluate(with: email)
    }
    
    // MARK: 密碼驗(yàn)證
    /// 密碼驗(yàn)證
    /// - Parameter password: 被校驗(yàn)字符串,8到20位,數(shù)字+小寫(xiě)+大寫(xiě)
    /// - Returns: 驗(yàn)證結(jié)果
    public static func checkPassword(_ password: String) -> Bool
    {
        let regex = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,20}$"
        let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
        return predicate.evaluate(with: password)
    }
    
    // MARK: 手機(jī)號(hào)驗(yàn)證(????)
    /// 手機(jī)號(hào)驗(yàn)證(????)
    /// - Parameter phone: 被校驗(yàn)字符串
    /// - Returns: 驗(yàn)證結(jié)果
    public static func checkPhone(_ phone: String) -> Bool
    {
        let regex = "^1[0-9]{10}$"
        let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
        return predicate.evaluate(with: phone)
    }
    
    // MARK: 數(shù)字驗(yàn)證
    /// 數(shù)字驗(yàn)證
    /// - Parameter number: 被校驗(yàn)字符串
    /// - Returns: 驗(yàn)證結(jié)果
    public static func checkNumber(_ number: String) -> Bool
    {
        if number.count == 0 { return false }
        let regex = "[0-9]*"
        let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
        return predicate.evaluate(with: number)
    }
    // MARK: 中文驗(yàn)證
    /// 中文驗(yàn)證
    /// - Parameter number: 被校驗(yàn)字符串
    /// - Returns: 驗(yàn)證結(jié)果
    public static func isChinese(_ string: String) -> Bool {
        let pattern = "[^\u{4e00}-\u{9fff}]"
        let predicate = NSPredicate(format: "SELF MATCHES %@", pattern)
        return !predicate.evaluate(with: string)
    }
    
    // MARK: 字母驗(yàn)證
    /// 字母驗(yàn)證
    /// - Parameter number: 被校驗(yàn)字符串
    /// - Returns: 驗(yàn)證結(jié)果
    public static func isEnglish(_ string: String) -> Bool {
        let letters = CharacterSet.letters
        return string.rangeOfCharacter(from: letters.inverted) == nil
    }
    
    // MARK: 檢查字符串是否包含一個(gè)或多個(gè)字母
    /// 檢查字符串是否包含一個(gè)或多個(gè)字母
    ///
    ///        checkLetter("123abc") -> true
    ///        checkLetter("123") -> false
    ///
    public static func checkLetter(_ string: String) -> Bool
    {
        let regex = "^[A-Za-z0-9]+$"
        let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
        return predicate.evaluate(with: string)
    }
    
    // MARK: 身份證弱驗(yàn)證
    /// 身份證弱驗(yàn)證(????),僅校驗(yàn)格式不驗(yàn)證校驗(yàn)碼
    /// - Parameter number: 被校驗(yàn)字符串
    /// - Returns: 驗(yàn)證結(jié)果
    public static func checkIdentityCardWeak(_ number: String) -> Bool {
        let count = number.count
        guard count == 15 || count == 18 else { return false }
        
        // 15位身份證:需全為數(shù)字
        if count == 15 {
            return number.allSatisfy(\.isNumber)
        }
        
        // 18位身份證:前17位需全為數(shù)字
        guard number.prefix(17).allSatisfy(\.isNumber) else {
            return false
        }
        
        // 第18位:數(shù)字或X/x
        let lastChar = number.last!
        return lastChar.isNumber || lastChar.lowercased() == "x"
    }
    // MARK: 身份證驗(yàn)證
    /// 身份證驗(yàn)證(????)
    /// - Parameter number: 被校驗(yàn)字符串
    /// - Returns: 驗(yàn)證結(jié)果
    public static func checkIdentityCard(_ number: String) -> Bool {
        let count = number.count
        guard count == 15 || count == 18 else {
            return false
        }
        
        var carid = number
        
        // 處理15位身份證轉(zhuǎn)換為18位
        if count == 15 {
            guard number.allSatisfy({ $0.isNumber }) else {
                return false
            }
            var mString = number
            mString.insert(contentsOf: "19", at: mString.index(mString.startIndex, offsetBy: 6))
            
            let R = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
            let sChecker: [Character] = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"]
            
            var sum = 0
            for i in 0..<17 {
                let char = mString[mString.index(mString.startIndex, offsetBy: i)]
                sum += Int(String(char))! * R[i]
            }
            let mod = sum % 11
            mString.append(String(sChecker[mod]))
            carid = mString
        }
        
        // 檢查地區(qū)碼
        guard carid.count == 18, areaCodeAt(String(carid.prefix(2))) else {
            return false
        }
        
        // 提取年月日
        let yearStart = carid.index(carid.startIndex, offsetBy: 6)
        let year = String(carid[yearStart..<carid.index(yearStart, offsetBy: 4)])
        let monthStart = carid.index(yearStart, offsetBy: 4)
        let month = String(carid[monthStart..<carid.index(monthStart, offsetBy: 2)])
        let dayStart = carid.index(monthStart, offsetBy: 2)
        let day = String(carid[dayStart..<carid.index(dayStart, offsetBy: 2)])
        
        // 驗(yàn)證年月日有效性
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyyMMdd"
        dateFormatter.locale = Locale(identifier: "en_US_POSIX")
        guard let _ = dateFormatter.date(from: "\(year)\(month)\(day)") else {
            return false
        }
        
        // 檢查前17位均為數(shù)字
        let chars = Array(carid)
        for i in 0..<17 where !chars[i].isNumber {
            return false
        }
        
        // 校驗(yàn)碼驗(yàn)證
        let R = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
        let sChecker: [Character] = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"]
        var sum = 0
        for i in 0..<17 {
            sum += Int(String(chars[i]))! * R[i]
        }
        let checkChar = sChecker[sum % 11]
        
        // 允許小寫(xiě)x并轉(zhuǎn)為大寫(xiě)比較
        return chars[17].uppercased() == String(checkChar)
    }

    // 地區(qū)碼驗(yàn)證方法保持不變
    public static func areaCodeAt(_ code: String) -> Bool {
        let areaCodes: [String: String] = [
            "11": "北京", "12": "天津", "13": "河北", "14": "山西", "15": "內(nèi)蒙古",
            "21": "遼寧", "22": "吉林", "23": "黑龍江", "31": "上海", "32": "江蘇",
            "33": "浙江", "34": "安徽", "35": "福建", "36": "江西", "37": "山東",
            "41": "河南", "42": "湖北", "43": "湖南", "44": "廣東", "45": "廣西",
            "46": "海南", "50": "重慶", "51": "四川", "52": "貴州", "53": "云南",
            "54": "西藏", "61": "陜西", "62": "甘肅", "63": "青海", "64": "寧夏",
            "65": "新疆", "71": "臺(tái)灣", "81": "香港", "82": "澳門(mén)", "91": "國(guó)外"
        ]
        return areaCodes[code] != nil
    }
}


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、通過(guò)CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明AI閱讀 16,203評(píng)論 3 119
  • 《今日頭條》這兩天上了自己的頭條 北上廣等14個(gè)城市的小伙伴們一覺(jué)醒來(lái),發(fā)現(xiàn)自己被“今天體”包圍了。 睡眼惺忪出門(mén)...
    一品內(nèi)容官閱讀 374評(píng)論 0 1
  • 在某一座孤島中的師范學(xué)校待了4年,熟悉的“下一站,大學(xué)城北”,熟悉的男女比例17比1,熟悉的b25,熟悉的新天地。...
    暮夕閱讀 329評(píng)論 0 1
  • 在我很多人生灰暗時(shí)刻是電視劇和書(shū)籍帶我度過(guò),當(dāng)我像外求時(shí),并沒(méi)有求得心安理得,所以最適合我的方式還是內(nèi)求
    子魚(yú)言閱讀 148評(píng)論 0 0

友情鏈接更多精彩內(nèi)容