Swift 使用正则表达式
Swift 中可以通过多种方式进行正则使用和匹配。每一种情况的应用场景都不一样,可选择一种适合自己的。
Tip:使用 Raw String 定义正则表达式,可以减少使用转义符号
\
普通字符串正则: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参数为regularExpression , 还有range参数是一个半闭String.index location指的是语言环境,一般为current
NSRegularExpression
NSRegularExpression 类可以用于正则配对和正则替换
正则匹配
/**
正则表达判断是否含有结果值
- parameter pattern: 一个字符串类型的正则表达式
parameter str: 需要比较判断的对象
- returns: 返回布尔值判断结果
warning: 注意匹配到结果的话就会返回true,没有匹配到结果就会返回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: 这里子串的获取先转话为NSString的[以后处理结果含NS的还是可以转换为NS前缀的方便]
returns: 返回目的字符串结果值数组(目前将String转换为NSString获得子串方法较为容易)
- warning: 注意匹配到结果的话就会返回true,没有匹配到结果就会返回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>) //本应该用这个的,可以无法直接获得参数,必须自己手动获取starIndex 和 endIndex作为区间
}
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)
}
不能使用先匹配,循环匹配结果来替换,会因为 range 不一致导致替换异常。
NSRange初始化 length参数为什么是字符串的 utf16.count?
这样可以避免 emoji 和类似的长度计算错误问题
NSRegularExpression.Options枚举
初始化正则的 option 项参数
枚举 | 描述 | 示例 |
---|---|---|
caseInsensitive | 不区分大小写 | Aa相当于 aa |
allowCommentsAndWhitespace | 忽略空格和#(注释) | A B#CC 相当于 AB |
ignoreMetacharacters | 整体化 | "AA\b"其中的\b不会当成匹配边界,而是字符串 |
dotMatcheshLineSeparators | 允许.匹配任何字符,包括行分隔符 | “a.b"可以匹配"a\nb” |
dotMatchesLines | 允许^和$匹配行的开头和结尾 | |
useUnixLineSeparators | 仅将\n视为行分隔符,否则,将使用所有标准行分隔符 | |
useUnicodeWordBoundaries | 使用Unicode TR#29指定单词边界,否则,使用传统的正则表达式单词边界 |
MathchingFlags
该枚举主要用于遍历闭包匹配方法enumerateMatches(in:options:range:using:)
的闭包回调参数中
typedef NS_OPTIONS(NSUInteger, NSMatchingFlags) {
//还在长时间的匹配中
NSMatchingProgress = 1 << 0,
//匹配已经完成
NSMatchingCompleted = 1 << 1,
//当前匹配操作到达搜索范围的末尾
NSMatchingHitEnd = 1 << 2,
//当前匹配项取决于搜索范围末端的位置
NSMatchingRequiredEnd = 1 << 3,
//由于内部错误而导致匹配失败而没有检查整个搜索范围
NSMatchingInternalError = 1 << 4
};
MatchingOptions枚举
该枚举主要用于遍历闭包匹配方法enumerateMatches(in:options:range:using:)
的参数
typedef NS_OPTIONS(NSUInteger, NSMatchingOptions) {
//在长时间的匹配操作期间,定期回调一次。
NSMatchingReportProgress = 1 << 0,
//当匹配完成时,回调一次。
NSMatchingReportCompletion = 1 << 1,
//只能匹配查询范围开始处的字符串 "aa"只能匹配"aabcd",而不能匹配"baabcd"
NSMatchingAnchored = 1 << 2,
//允许匹配超出搜索范围的范围,例如文字边界检测,前瞻等。如果搜索范围包含整个字符串,该选项将不起作用
NSMatchingWithTransparentBounds = 1 << 3,
//防止^和$自动匹配搜索范围的开始和结束,如果搜索范围包含整个字符串,该选项 将不起作用
//"^ab"默认能匹配NSMakeRange(1, 3)]范围上的"babcd"
//当使用该选项时,则不能匹配
NSMatchingWithoutAnchoringBounds = 1 << 4
};
常用的就是这三种方式中使用正则表达式字符串 ,其中第一、二种较为方便的判断是否含有值,和只匹配一次的情况,而第三种可以匹配返回多个目的值。
正则语言速预览
NSRegularExpression 正则语法 – Apple 官方
正则表达式语法 – 菜鸟教程
在线正则–regular expresssions可以标记组和各项匹配,还可以进行正则语法检查。
JS 正则表达式完整教程–掘金详细介绍正则的基本和高级使用
匹配所有字符:[\s\S]
分组
通过()可以进行分组标记,在匹配成功后,可以通过下表来获取到对应组的值。
示例:获取匹配到的年月日
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)
,这样第一个括号就不会被捕获。
零宽度断点
零宽度断点:它匹配的内容不会提取,而是匹配到的一个位置。
主要应用场景如下:
- 排除查找,查找不包含有某段字符串的行
- 包含查找,查找包含某段字符串的行
正则表达式-零度断言包含使用场景,使用介绍和示例,通过先匹配后检查来简单区分各种不同的零度断言。
贪婪/非贪婪匹配
在表中,有一项为量词,默认都是贪婪匹配,即按照最多情况匹配到,而通过在量词后添加?
即可实现非贪婪匹配。
比如待匹配文本:a,b,c,d,
贪婪匹配:.*,
结果为:a,b,c,d, 只能匹配到1项
非贪婪匹配:.*?,
结果为:a, b, c, d, 能匹配到4项文章来源:https://www.toymoban.com/news/detail-421497.html
文章来源地址https://www.toymoban.com/news/detail-421497.html
到了这里,关于Swfit 使用正则表达式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!