swift中的正则表达式小结
正则表达式是对字符串操作的一种逻辑公式,用事先定义好的一些特定字符、及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑。
作为一门先进的编程语言,Swift可以说吸收了众多其他先进语言的优点,但是有一点却是让人略微失望的,就是Swift至今为止并没有在语言层面上支持正则表达式。
正则表达式的用处:
判断给定的字符串是否符合某一种规则(专门用于操作字符串)
-电话号码,电子邮箱,URL...
-可以直接百度别人写好的正则
-别人真的写好了,而且测试过了,我们可以直接用
-要写出没有漏洞正则判断,需要大量的测试,通常最终结果非常负责
过滤筛选字符串,网络爬虫
替换文字,QQ聊天,图文混排
语法规则
使用过程
1、创建规则2、创建正则表达式对象3、开始匹配
代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 privatefunccheck(str:String){
//使用正则表达式一定要加try语句
do{
//-1、创建规则
letpattern="[1-9][0-9]{4,14}"
//-2、创建正则表达式对象
letregex=tryNSRegularExpression(pattern:pattern,options:NSRegularExpressionOptions.CaseInsensitive)
//-3、开始匹配
letres=regex.matchesInString(str,options:NSMatchingOptions(rawValue:0),range:NSMakeRange(0,str.characters.count))
//输出结果
forcheckingResinres{
print((strasNSString).substringWithRange(checkingRes.range))
}
}
catch{
print(error)
}
} 其他几个常用方法
1
2
3
4
5
6
7
8
9
10 //匹配字符串中所有的符合规则的字符串,返回匹配到的NSTextCheckingResult数组
publicfuncmatchesInString(string:String,options:NSMatchingOptions,range:NSRange)->[NSTextCheckingResult]
//按照规则匹配字符串,返回匹配到的个数
publicfuncnumberOfMatchesInString(string:String,options:NSMatchingOptions,range:NSRange)->Int
//按照规则匹配字符串,返回第一个匹配到的字符串的NSTextCheckingResult
publicfuncfirstMatchInString(string:String,options:NSMatchingOptions,range:NSRange)->NSTextCheckingResult?
//按照规则匹配字符串,返回第一个匹配到的字符串的范围
publicfuncrangeOfFirstMatchInString(string:String,options:NSMatchingOptions,range:NSRange)->NSRange 使用子类来匹配日期、地址、和URL
看官网文档解释,可以知道这个NSDataDetector主要用来匹配日期、地址、和URL。在使用时指定要匹配的类型
1
2
3
4
5
6
7
8
9
10
11 publicclassNSDataDetector:NSRegularExpression{
//allinstancevariablesareprivate
/NSDataDetectorisaspecializedsubclassofNSRegularExpression.Insteadoffindingmatchestoregularexpressionpatterns,itmatchesitemsidentifiedbyDataDetectors,suchasdates,addresses,andURLs.ThecheckingTypesargumentshouldcontainoneormoreofthetypesNSTextCheckingTypeDate,NSTextCheckingTypeAddress,NSTextCheckingTypeLink,NSTextCheckingTypePhoneNumber,andNSTextCheckingTypeTransitInformation.TheNSTextCheckingResultinstancesreturnedwillbeoftheappropriatetypesfromthatlist.
/
publicinit(typescheckingTypes:NSTextCheckingTypes)throws
publicvarcheckingTypes:NSTextCheckingTypes{get}
}
//这个是类型选择
publicstaticvarDate:NSTextCheckingType{get}//date/timedetection
publicstaticvarAddress:NSTextCheckingType{get}//addressdetection
publicstaticvarLink:NSTextCheckingType{get}//linkdetection NSDataDetector获取URL示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 /
匹配字符串中的URLS
-parameterstr:要匹配的字符串
/
privatefuncgetUrl(str:String){
//创建一个正则表达式对象
do{
letdataDetector=tryNSDataDetector(types:NSTextCheckingTypes(NSTextCheckingType.Link.rawValue))
//匹配字符串,返回结果集
letres=dataDetector.matchesInString(str,options:NSMatchingOptions(rawValue:0),range:NSMakeRange(0,str.characters.count))
//取出结果
forcheckingResinres{
print((strasNSString).substringWithRange(checkingRes.range))
}
}
catch{
print(error)
}
} ".?"可以满足一些基本的匹配要求
如果想同时匹配多个规则,可以通过"|"将多个规则连接起来
将字符串中文字替换为表情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 /
显示字符中的表情
-parameterstr:匹配字符串
/
privatefuncgetEmoji(str:String){
letstrM=NSMutableAttributedString(string:str)
do{
letpattern="\\[.?\\]"
letregex=tryNSRegularExpression(pattern:pattern,options:NSRegularExpressionOptions.www.hunanwang.netCaseInsensitive)
letres=regex.matchesInString(str,options:NSMatchingOptions(rawValue:0),range:NSMakeRange(0,str.characters.count))
varcount=res.count
//反向取出文字表情
whilecount>0{
letcheckingRes=res[--count]
lettempStr=(strasNSString).substringWithRange(checkingRes.range)
//转换字符串到表情
ifletemoticon=EmoticonPackage.emoticonWithStr(tempStr){
print(emoticon.chs)
letattrStr=EmoticonTextAttachment.imageText(emoticon,font:18)
strM.replaceCharactersInRange(checkingRes.range,withAttributedString:attrStr)
}
}
print(strM)
//替换字符串,显示到label
emoticonLabel.attributedText=strM
}
catch{
print(error)
}
} 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 /
只要textStorage中的内容发生变化,就可以通知layoutManager重新布局
layoutManager重新布局需要知道绘制到什么地方,所以layoutManager就会文textContainer绘制的区域
/
//准们用于存储内容的
//textStorage中有layoutManager
privatelazyvartextStorage=NSTextStorage()
//专门用于管理布局
//layoutManager中有textContainer
privatelazyvarlayoutManager=NSLayoutManager()
//专门用于指定绘制的区域
privatelazyvartextContainer=NSTextContainer()
overrideinit(frame:CGRect){
super.init(frame:frame)
setupSystem()
}
requiredinit?(coderaDecoder:NSCoder){
super.init(coder:aDecoder)
setupSystem()
}
privatefuncsetupSystem()
{
//1.将layoutManager添加到textStorage
textStorage.addLayoutManager(layoutManager)
//2.将textContainer添加到layoutManager
layoutManager.addTextContainer(textContainer)
}
overridefunclayoutSubviews(){
super.layoutSubviews()
//3.指定区域
textContainer.size=bounds.size
} 1
2
3
4
5
6
7
8
9
10
11
12
13 overridevartext:String?
{
didSet{
//1.修改textStorage存储的内容
textStorage.setAttributedString(NSAttributedString(string:text!))
//2.设置textStorage的属性
textStorage.addAttribute(NSFontAttributeName,value:UIFont.systemFontOfSize(20),range:NSMakeRange(0,text!www.visa158.com.characters.count))
//3.处理URL
self.URLRegex()
//2.通知layoutManager重新布局
setNeedsDisplay()
}
} 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 funcURLRegex()
{
//1.创建一个正则表达式对象
do{
letdataDetector=tryNSDataDetector(types:NSTextCheckingTypes(NSTextCheckingType.Link.rawValue))
letres=dataDetector.matchesInString(textStorage.string,options:NSMatchingOptions(rawValue:0),range:NSMakeRange(0,textStorage.string.characters.count))
//4取出结果
forcheckingResinres
{
letstr=(textStorage.stringasNSString).substringWithRange(checkingRes.range)
lettempStr=NSMutableAttributedString(string:str)
//tempStr.addAttribute(NSForegroundColorAttributeName,value:UIColor.redColor(),range:NSMakeRange(0,str.characters.count))
tempStr.addAttributes([NSFontAttributeName:UIFont.systemFontOfSize(20),NSForegroundColorAttributeName:UIColor.redColor()],range:NSMakeRange(0,str.characters.count))
textStorage.replaceCharactersInRange(checkingRes.range,withAttributedString:tempStr)
}
}catch
{
print(error)
}
} 4、重绘文字
1
2
3
4
5
6
7
8
9
10 //如果是UILabel调用setNeedsDisplay方法,系统会促发drawTextInRect
overridefuncdrawTextInRect(rect:CGRect){
//重绘
//字形:理解为一个小的UIView
/
第一个参数:指定绘制的范围
第二个参数:指定从什么位置开始绘制
/
layoutManager.drawGlyphsForGlyphRange(NSMakeRange(0,text!.characters.count),atPoint:CGPointZero)
} 获取label中URL的点击
如果要获取URL的点击,那么必须获取点击的范围
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 overridefunctouchesBegan(touches:Set,withEventevent:UIEvent?){
//1、获取手指点击的位置
lettouch=(touchesasNSSet).anyObject()!
letpoint=touch.locationInView(touch.view)
print(point)
//2、获取URL区域
//注意:没有办法直接设置UITextRange的范围
letrange=NSMakeRange(10,20)
//只要设置selectedRange,那么就相当于设置了selectedTextRange
selectedRange=range
//给定指定的range,返回range对应的字符串的rect
//返回数组的原因是因为文字可能换行
letarray=selectionRectsForRange(selectedTextRange!)
forselectionRectinarray{
ifCGRectContainsPoint(selectionRect.rect,point){
print("点击了URL")
}
}
}
|
|