- 正则表达式是对字符串操作的一种逻辑公式,用事先定义好的一些特定字符、及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑。
正则表达式的用处:
-
- 判断给定的字符串是否符合某一种规则(专门用于操作字符串)
- 电话号码,电子邮箱,URL...
- 可以直接百度别人写好的正则
- 别人真的写好了,而且测试过了,我们可以直接用
- 要写出没有漏洞正则判断,需要大量的测试,通常最终结果非常负责
-
- 过滤筛选字符串,网络爬虫
-
- 替换文字,QQ聊天,图文混排
语法规则
[xyz] 字符集合(x/y或z)
[a-z] 字符范围
[a-zA-Z]
[^xyz] 负值字符集合 (任何字符, 除了xyz)
[^a-z] 负值字符范围 [a-d][m-p] 并集(a到d 或 m到p)
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字 [a-zA-Z_0-9]
\s 匹配任意的空白符(空格、TAB\t、回车\r \n)
\d 匹配数字 [0-9]
^ 匹配字符串的开始
$ 匹配字符串的结束
\b 匹配单词的开始或结束
\W 匹配任意不是字母,数字,下划线,汉字的字符[^\w]
\S 匹配任意不是空白符的字符 [^\s]
\D 匹配任意非数字的字符[^0-9]
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次,
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
使用过程
- 1、创建规则
- 2、创建正则表达式对象
- 3、开始匹配
代码示例
private func check(str: String) {
do {
let pattern = "[1-9][0-9]{4,14}"
let regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions.CaseInsensitive)
let res = regex.matchesInString(str, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, str.characters.count))
for checkingRes in res {
print((str as NSString).substringWithRange(checkingRes.range))
}
}
catch {
print(error)
}
}
public func matchesInString(string: String, options: NSMatchingOptions, range: NSRange) -> [NSTextCheckingResult]
public func numberOfMatchesInString(string: String, options: NSMatchingOptions, range: NSRange) -> Int
public func firstMatchInString(string: String, options: NSMatchingOptions, range: NSRange) -> NSTextCheckingResult?
public func rangeOfFirstMatchInString(string: String, options: NSMatchingOptions, range: NSRange) -> NSRange
使用子类来匹配日期、地址、和URL
- 看官网文档解释,可以知道这个
NSDataDetector
主要用来匹配日期、地址、和URL。在使用时指定要匹配的类型
public class NSDataDetector : NSRegularExpression {
public init(types checkingTypes: NSTextCheckingTypes) throws
public var checkingTypes: NSTextCheckingTypes { get }
}
public static var Date: NSTextCheckingType { get }
public static var Address: NSTextCheckingType { get }
public static var Link: NSTextCheckingType { get }
private func getUrl(str:String) {
do {
let dataDetector = try NSDataDetector(types: NSTextCheckingTypes(NSTextCheckingType.Link.rawValue))
let res = dataDetector.matchesInString(str, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, str.characters.count))
for checkingRes in res {
print((str as NSString).substringWithRange(checkingRes.range))
}
}
catch {
print(error)
}
}
- ".*?" 可以满足一些基本的匹配要求
- 如果想同时匹配多个规则 ,可以通过 "|" 将多个规则连接起来
- 将字符串中文字替换为表情
private func getEmoji(str:String) {
let strM = NSMutableAttributedString(string: str)
do {
let pattern = "\\[.*?\\]"
let regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions.CaseInsensitive)
let res = regex.matchesInString(str, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, str.characters.count))
var count = res.count
while count > 0 {
let checkingRes = res[--count]
let tempStr = (str as NSString).substringWithRange(checkingRes.range)
if let emoticon = EmoticonPackage.emoticonWithStr(tempStr) {
print(emoticon.chs)
let attrStr = EmoticonTextAttachment.imageText(emoticon, font: 18)
strM.replaceCharactersInRange(checkingRes.range, withAttributedString: attrStr)
}
}
print(strM)
emoticonLabel.attributedText = strM
}
catch {
print(error)
}
}
TextKit
给URL高亮显示
- 主要用到三个类
NSTextStorage
NSLayoutManager
NSTextContainer
自定义UILabel来实现url高亮
private lazy var textStorage = NSTextStorage()
private lazy var layoutManager = NSLayoutManager()
private lazy var textContainer = NSTextContainer()
override init(frame: CGRect) {
super.init(frame: frame)
setupSystem()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupSystem()
}
private func setupSystem()
{
textStorage.addLayoutManager(layoutManager)
layoutManager.addTextContainer(textContainer)
}
override func layoutSubviews() {
super.layoutSubviews()
textContainer.size = bounds.size
}
override var text: String?
{
didSet{
textStorage.setAttributedString(NSAttributedString(string: text!))
textStorage.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(20), range: NSMakeRange(0, text!.characters.count))
self.URLRegex()
setNeedsDisplay()
}
}
func URLRegex()
{
do{
let dataDetector = try NSDataDetector(types: NSTextCheckingTypes(NSTextCheckingType.Link.rawValue))
let res = dataDetector.matchesInString(textStorage.string, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, textStorage.string.characters.count))
for checkingRes in res
{
let str = (textStorage.string as NSString).substringWithRange(checkingRes.range)
let tempStr = NSMutableAttributedString(string: str)
tempStr.addAttributes([NSFontAttributeName: UIFont.systemFontOfSize(20), NSForegroundColorAttributeName: UIColor.redColor()], range: NSMakeRange(0, str.characters.count))
textStorage.replaceCharactersInRange(checkingRes.range, withAttributedString: tempStr)
}
}catch
{
print(error)
}
}
override func drawTextInRect(rect: CGRect) {
layoutManager.drawGlyphsForGlyphRange(NSMakeRange(0, text!.characters.count), atPoint: CGPointZero)
}
获取label中URL的点击
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = (touches as NSSet).anyObject()!
let point = touch.locationInView(touch.view)
print(point)
let range = NSMakeRange(10, 20)
selectedRange = range
let array = selectionRectsForRange(selectedTextRange!)
for selectionRect in array {
if CGRectContainsPoint(selectionRect.rect, point) {
print("点击了URL")
}
}
}