正则表达式

2016-11-02  本文已影响106人  BigBossZhu

正则表达式

纯文本做限制处理.可以用来检查一个字符串是否包含某种子串,将匹配的子串做替换或者从某个串中取出符合某个

作用:模式匹配(子串的定位操作),替换,效率高且简单.语法后台玩的比较溜,工作中不会的可以找他们.

  1. 数据验证
  2. 替换文本
  3. 提取子字符串

掌握正则表达式在OC代码中使用.

关键词: Regular Expression(正则表达式)
核心类: NSRegularExpression(NS框架下的,不需要导入):用来表达应用正则表达式.

注意点:

  1. 正则表达式很容易写错,所以一定要做错误处理
  2. 创建正则表达式.
  3. 查找相关内容.

- (void)regularExpression {
    NSString *content = @"蓝瘦, 香菇, 本来今天高高兴兴, 你为什么要说这种话, 蓝瘦, 在这里, 香菇! 第一次喂了一个女孩屎";
    //创建正则对象,配置参数
    // Pattern(模式), 要填的是`正则语法`所组成的`匹配模式`, 作用是告诉正则, 要查找的是什么("蓝瘦")
    NSString *pattren = @"香菇";
    // NSRegularExpressionOptions 正则表达式的匹配查找选项, 通常会给0, 因为正则语法可以实现这此功能
    // 错误处理,必须要做
    NSError *error;
    NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:pattren options:0 error:&error];
    if (error) {
        NSLog(@"创建正则失败");
    }
    
    
    /**
     // 查找第一次匹配结果
     参数一:在哪个字符串中匹配
     参数二:匹配查找选项,选0
     参数三:在这个字符串的哪个范围中匹配
     */
    NSTextCheckingResult *result = [regular firstMatchInString:content options:0 range:NSMakeRange(0, content.length)];
    NSLog(@"%@",NSStringFromRange(result.range));
    NSLog(@"%@",[content substringWithRange:result.range]);
    
    /**
     全部匹配
     参数1 NSString content
     参数2 0
     参数3 content的查找范围
     返回数组 results
     */
    NSArray<NSTextCheckingResult *> *results = [regular matchesInString:content options:0 range:NSMakeRange(0, content.length)];
    //遍历
    for (NSTextCheckingResult *result in results) {
        NSLog(@"%@",NSStringFromRange(result.range));
        NSLog(@"%@",[content substringWithRange:result.range]);
    }
}

目标:掌握一些正则的基本语法
  1. @"55555" -> @"5{5}" 中{}是功能性字符,表示重复5次
  2. @"5{3,7}" :{3,7}表示重复3~7次,会尽量找到多的.
  3. @"5+" :+表示至少有一个,默认只修饰前面一个
  4. @"(123)+" :()加小括号改变优先级,修饰一个整体.
  5. @"[136]" :[]代表组合,可以是其中的任意一个.
  6. 只要含数字: @"[0123456789]+" -> @"[0-9]+".-代表范围
  7. @"\d" :元字符(转义字符),\d在正则当中表示任意整数,\d等价[0-9]
    注意:OC的字符串中,\d正则不能直接写,所以要写\d.
  8. 找到字符:@"[a-z]+"
  9. @"\w":表示\w正则表示字符,汉字下划线,数字.OC中写\w
  10. @"\w和[\w]":在没有[]时,他表示的是匹配字符串的开始.^在[]里面,表示取反,表示并非是这个类型的字符串的开始.
    还要理解一下.
  11. @".com$": $表示匹配到字符串结束.
  12. @"(0|86)?" :表示以0或86或空(?).
正则练习
// 匹配QQ号码,匹配规则:全部是都是数字,第一个字符非0,长度为(6~11)
     ^[1-9]\\d{5,10}$
    // [^0],[1-9]    \d,[0-9]  {5,10}
    //    NSString *result = [@"48584958" firstStringMatchWithPattern:@"^[1-9]\\d{5,10}$"];
    //    NSLog(@"%@", result);
    
    // 匹配规则:以0或86或空开头,后面第一个数字为"1",当第二数字为 "3,5,8" 第三个数字为"0-9",当第二数字为"7" 第三个数字为"6或7或8",当第二个数字为"4"时,第三个数字为"5或7",手机号码位数为11位.
    // ^ (0|86)? 1 ( ([358][0-9]) | (7[678]) | 4[57] ) \d{8} $
    // ? 表示可有可无, 类似于bool
    NSString *result = [@"13800138000" firstStringMatchWithPattern:@"^(0|86)?1(([358][0-9])|(7[678])|4[57])\\d{8}$"];

提取分类文件保留.

正则实际用法:(重要),研究一下.

一种设计思想(都是用正则做的)
微信中的默认表情包的表情发送情况分析:

  1. 发送方与接收方, 规定一些特定的字符, 用来表示表情 如 [微笑] , /微笑
  2. 发送方: 在发消息之前, 将带有表情的文字转换成纯文字
    如: 你好!约吗(微笑表情) (富文本) --> 你好!约吗[smile.png] (纯文本)
  3. 接收方: 在收到消息后, 显示之前, 会做处理
    如: 你好!约吗[smile.png] --> 你好!约吗(微笑表情)

利用应用名来定义一份协议,再用正则来匹配协议.

微信扫二维码添加好友的思路分析:
微信扫描二维码的字符串
我先子定一个协议以Wechat://Action=Adduser?UserID=科比?message="你好我是谁谁谁,请求验证."

  1. 假设Action 表示 添加好友, 调用相关代码来实现功能
  2. 假设 UserID 表示添加的好友ID的参数, message 表示添加好友的消息的参数
  3. 调用添加好友的功能代码, 将相关参数给它.

二维码http://跳转网页的思路逻辑:

示例Demo:将表情图片名换成真正的图片名.

实现富文本(带有表情图片):富文本可以带附件NSTextAttachment类.

NSAttributedString

  1. 查找文本 -> 是否有表情图片的文字:正则表达式
  2. 利用富文本实现图文混排.

// [表情名] :[]在正则里面有特殊意义,所以\[表示普通的],正则转义
// [\w+]->转化为OC还要转义@"\[\w+\]"

  1. 正则查找图片格式字符串,获取到这个字符串.

  2. 转化为文字

  3. 富文本显示图片加文字.(替换表情字符串为图片附件字符串)

注意

  1. 表情符号的高度与Lable不匹配的解决办法.自定义类继承NSTextAttachment,一个快速的方法使其高度相等,** 修改它的y值,为-高度*0.2 **

  2. 多张表情图片的替换

注意数组越界问题:原因,因为替换的原理导致你的字符串的range减少,所以产生越界问题.但是还是以原来的来取.
解决办法,** 从尾部替换 **.

// 返回附件在它的容器当中的位置
- (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(CGRect)lineFrag glyphPosition:(CGPoint)position characterIndex:(NSUInteger)charIndex
{
//继承系统的NSTextAttachment类.修改表情使其高度相同
    // 附件所处的容器的大小
    NSLog(@"lineFrag: %@", NSStringFromCGRect(lineFrag));
    // 附件在它的显示容器当中的位置
    NSLog(@"position: %@", NSStringFromCGPoint(position));
    // 附件所处文本在原始文本当中的位置(索引)
    NSLog(@"%zd", charIndex);
    
    // 返回的附件的大小, 与label的高度一样 (与文字接近)
    // 简单粗暴: -lineFrag.size.height * 0.2;  (StackOverFlow)
#pragma mark - 修改表情高度与Lable相同(开始会高一些)
    return CGRectMake(0, -lineFrag.size.height * 0.2, lineFrag.size.height, lineFrag.size.height);
    // 科学合理(不好解释): 要根据字体来决定该值
//    return CGRectMake(0, self.font.descender, lineFrag.size.height, lineFrag.size.height);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    self.label.text = @"蓝瘦, 香菇[smiley_1], 在这里, 第一次喂了一个女孩屎[smiley_6], 这么香菇[smiley_19]!";
    // 正则表达式只能针对纯文本NSString进行匹配, 不能NSAttributedString
    NSString *content = self.label.text;
    
    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:content];
    
    // 1. 找到所有的图片(封装好了正则表达式)
    NSArray *rangeArray = [content matchesRangeWithPattern:@"\\[\\w+\\]"];
    if (rangeArray == nil) {
        return;
    }
    
    for (int i = 0; i < rangeArray.count; i++) {
        // 倒过来读取数组的元素
        NSValue *value = rangeArray[rangeArray.count - i - 1];
        // 每一个表情[表情图片]的范围
        NSRange range = value.rangeValue;
        
        // 获取每张图片图片
        UIImage *image = [UIImage imageNamed:[content substringWithRange:NSMakeRange(range.location + 1, range.length - 2)]];
        
        // 创建表情图片对应NSAttributedString
        HMTextAttament *attachment = [[HMTextAttament alloc] init];
        attachment.image = image;
        NSAttributedString *imageString = [NSAttributedString attributedStringWithAttachment:attachment];
        NSLog(@"%zd", imageString.length);
        
        // 替换文本
        [attrString replaceCharactersInRange:range withAttributedString:imageString];
    }
    
    // 已经全部替换完成
    self.label.attributedText = attrString;
}

** 注意:正则表达式只能匹配纯文本NSString,不能匹配NSAttributedString. **

上一篇 下一篇

猜你喜欢

热点阅读