Swift 使用正則表達式
Swift 中可以通過多種方式進行正則使用和匹配。每一種情況的應(yīng)用場景都不一樣,可選擇一種適合自己的。
Tip:使用 Raw String 定義正則表達式,可以減少使用轉(zhuǎn)義符號
\
普通字符串正則:let pattern = “\\d{3,11}”
擴展分隔符正則:let pattern = #“\d{3,11}”#
通過 NSpredicate 匹配正則(不推薦)
let email = "lifusc464@qq.com"
let regex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
let isValid = predicate.evaluate(with: email)
print(isValid ? "正確的郵箱地址" : "錯誤的郵箱地址")
利用String的RangeOfString: option: 直接查找
let email = "lifusc148387@qq.com"
let rangeindex = email.range(of: "[0-9]{4}", options: .regularExpression, range: email.startIndex..<email.endIndex, locale:Locale.current)
print(email.substring(with: rangeindex!)) //輸出;1483
注意使用的option參數(shù)為regularExpression , 還有range參數(shù)是一個半閉String.index location指的是語言環(huán)境,一般為current
NSRegularExpression
NSRegularExpression 類可以用于正則配對和正則替換
正則匹配
/**
正則表達判斷是否含有結(jié)果值
- parameter pattern: 一個字符串類型的正則表達式
parameter str: 需要比較判斷的對象
- returns: 返回布爾值判斷結(jié)果
warning: 注意匹配到結(jié)果的話就會返回true,沒有匹配到結(jié)果就會返回false
*/
class func regex(pattern:String, str:String) -> Bool {
let regex = try! NSRegularExpression(pattern: pattern, options:[NSRegularExpression.Options.caseInsensitive])
let resultNum = regex.numberOfMatches(in: str, options: NSRegularExpression.MatchingOptions(rawValue: 0) , range: NSMakeRange(0, str.characters.count))
if resultNum>=1 {
return true
}
return false
}
/**
正則表達式獲取目的值
- parameter pattern: 一個字符串類型的正則表達式
parameter str: 需要比較判斷的對象
- imports: 這里子串的獲取先轉(zhuǎn)話為NSString的[以后處理結(jié)果含NS的還是可以轉(zhuǎn)換為NS前綴的方便]
returns: 返回目的字符串結(jié)果值數(shù)組(目前將String轉(zhuǎn)換為NSString獲得子串方法較為容易)
- warning: 注意匹配到結(jié)果的話就會返回true,沒有匹配到結(jié)果就會返回false
*/
class func regexGetSub(pattern:String, str:String) -> [String] {
var subStr = [String]()
let regex = try! NSRegularExpression(pattern: pattern, options:[NSRegularExpression.Options.caseInsensitive])
let results = regex.matches(in: str, options: NSRegularExpression.MatchingOptions.init(rawValue: 0), range: NSMakeRange(0, str.characters.count))
//解析出子串
for rst in results {
let nsStr = str as NSString //可以方便通過range獲取子串
subStr.append(nsStr.substring(with: rst.range))
//str.substring(with: Range<String.Index>) //本應(yīng)該用這個的,可以無法直接獲得參數(shù),必須自己手動獲取starIndex 和 endIndex作為區(qū)間
}
return subStr
}
正則替換
func replaceString() {
let givenString = "hello,world"
guard let regularExpression = try? NSRegularExpression(pattern: "hello") else { return }
let replacedString = regularExpression.stringByReplacingMatches(in: givenString, range: NSRange(location: 0, length: givenString.utf16.count), withTemplate: "你好")
print(replacedString)
}
不能使用先匹配,循環(huán)匹配結(jié)果來替換,會因為 range 不一致導(dǎo)致替換異常。
NSRange初始化 length參數(shù)為什么是字符串的 utf16.count?
這樣可以避免 emoji 和類似的長度計算錯誤問題
NSRegularExpression.Options枚舉
初始化正則的 option 項參數(shù)
枚舉 | 描述 | 示例 |
---|---|---|
caseInsensitive | 不區(qū)分大小寫 | Aa相當于 aa |
allowCommentsAndWhitespace | 忽略空格和#(注釋) | A B#CC 相當于 AB |
ignoreMetacharacters | 整體化 | "AA\b"其中的\b不會當成匹配邊界,而是字符串 |
dotMatcheshLineSeparators | 允許.匹配任何字符,包括行分隔符 | “a.b"可以匹配"a\nb” |
dotMatchesLines | 允許^和$匹配行的開頭和結(jié)尾 | |
useUnixLineSeparators | 僅將\n視為行分隔符,否則,將使用所有標準行分隔符 | |
useUnicodeWordBoundaries | 使用Unicode TR#29指定單詞邊界,否則,使用傳統(tǒng)的正則表達式單詞邊界 |
MathchingFlags
該枚舉主要用于遍歷閉包匹配方法enumerateMatches(in:options:range:using:)
的閉包回調(diào)參數(shù)中
typedef NS_OPTIONS(NSUInteger, NSMatchingFlags) {
//還在長時間的匹配中
NSMatchingProgress = 1 << 0,
//匹配已經(jīng)完成
NSMatchingCompleted = 1 << 1,
//當前匹配操作到達搜索范圍的末尾
NSMatchingHitEnd = 1 << 2,
//當前匹配項取決于搜索范圍末端的位置
NSMatchingRequiredEnd = 1 << 3,
//由于內(nèi)部錯誤而導(dǎo)致匹配失敗而沒有檢查整個搜索范圍
NSMatchingInternalError = 1 << 4
};
MatchingOptions枚舉
該枚舉主要用于遍歷閉包匹配方法enumerateMatches(in:options:range:using:)
的參數(shù)
typedef NS_OPTIONS(NSUInteger, NSMatchingOptions) {
//在長時間的匹配操作期間,定期回調(diào)一次。
NSMatchingReportProgress = 1 << 0,
//當匹配完成時,回調(diào)一次。
NSMatchingReportCompletion = 1 << 1,
//只能匹配查詢范圍開始處的字符串 "aa"只能匹配"aabcd",而不能匹配"baabcd"
NSMatchingAnchored = 1 << 2,
//允許匹配超出搜索范圍的范圍,例如文字邊界檢測,前瞻等。如果搜索范圍包含整個字符串,該選項將不起作用
NSMatchingWithTransparentBounds = 1 << 3,
//防止^和$自動匹配搜索范圍的開始和結(jié)束,如果搜索范圍包含整個字符串,該選項 將不起作用
//"^ab"默認能匹配NSMakeRange(1, 3)]范圍上的"babcd"
//當使用該選項時,則不能匹配
NSMatchingWithoutAnchoringBounds = 1 << 4
};
常用的就是這三種方式中使用正則表達式字符串 ,其中第一、二種較為方便的判斷是否含有值,和只匹配一次的情況,而第三種可以匹配返回多個目的值。
正則語言速預(yù)覽
NSRegularExpression 正則語法 – Apple 官方
正則表達式語法 – 菜鳥教程
在線正則–regular expresssions可以標記組和各項匹配,還可以進行正則語法檢查。
JS 正則表達式完整教程–掘金詳細介紹正則的基本和高級使用
匹配所有字符:[\s\S]
分組
通過()可以進行分組標記,在匹配成功后,可以通過下表來獲取到對應(yīng)組的值。
示例:獲取匹配到的年月日
func regularExpressionGroup() {
let givenString = "2022-04-28"
guard let regularExpression = try? NSRegularExpression(pattern: #"(\d{4,})-(\d{1,2})-(?<day>\d{1,2})"#) else { return }
let results = regularExpression.matches(in: givenString, range: NSRange(location: 0, length: givenString.utf16.count))
for result in results {
//let all = result.range(at: 0) // 匹配到的整個字符串
let yearRange = result.range(at: 1) //匹配到的組1
print("年")
print(givenString[Range<String.Index>.init(yearRange, in: givenString)!])
let monthRange = result.range(at: 2)
print("月")
print(givenString[Range<String.Index>.init(monthRange, in: givenString)!])
let dayRange = result.range(withName: "day")
print("日")
print(givenString[Range<String.Index>.init(dayRange, in: givenString)!])
}
}
建議通過 name 來定義組
自定義組名的使用方式為
(?<name>子表達式)
嵌套組怎么確定 index?
以左邊括號(
為次序
不想捕獲組怎么辦?
可以在左括號后添加?:
比如(?:\d)-(\d)
,這樣第一個括號就不會被捕獲。
零寬度斷點
零寬度斷點:它匹配的內(nèi)容不會提取,而是匹配到的一個位置。
主要應(yīng)用場景如下:
- 排除查找,查找不包含有某段字符串的行
- 包含查找,查找包含某段字符串的行
正則表達式-零度斷言包含使用場景,使用介紹和示例,通過先匹配后檢查來簡單區(qū)分各種不同的零度斷言。
貪婪/非貪婪匹配
在表中,有一項為量詞,默認都是貪婪匹配,即按照最多情況匹配到,而通過在量詞后添加?
即可實現(xiàn)非貪婪匹配。
比如待匹配文本:a,b,c,d,
貪婪匹配:.*,
結(jié)果為:a,b,c,d, 只能匹配到1項
非貪婪匹配:.*?,
結(jié)果為:a, b, c, d, 能匹配到4項文章來源:http://www.zghlxwxcb.cn/news/detail-421497.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-421497.html
到了這里,關(guān)于Swfit 使用正則表達式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!