iOS 正则表达式切割字符串的应用

2018-11-29  本文已影响15人  woniu

背景:近来公司需要做音频书的颜色高亮功能,也就是音频读到哪里,文字也就随着变色。这样的话也就用到了文本的内容切割问题就来了。

一、字符串的切割

下面我们展示下我们要切割的部分文本内容:

 NSString *textString  = @"###弗洛伦蒂诺·阿里萨选择了这个时候向乌尔比诺的妻子费尔米娜·达萨
表白了心迹,但是她被他的唐突,以及自己所感到的内心深处触发出的情感所吓退。当他们都年轻
的时候,她和弗洛伦蒂诺互相交换了许多炽热的情书,并且曾经决定结婚。而再次见到他时,费尔明
娜却“惊慌地自问,怎么会如此残酷地让那样一个幻影在自己的心间占据了那么长时间”,并对他说
“忘了吧”。弗洛伦蒂诺则珍守着对她的渴望,并且决心为她保持童贞直到他们最终能够走到一起。
然而他很快发现自己用放纵的生活来排遣分离的空虚,费尔米娜嫁给了乌尔比诺医生?成为了他忠实
的伴侣。而医生本人也有着相似但比较简短的一段前事。";

从文本上看,我们获取需要获取每一段的句子,然后在获取每一句的字符长度,于是我想到了字符串的切割,如下:

  NSArray *array = [textString componentsSeparatedByString:@"。"]; //从字符A中分隔成2个元素的数组
    NSString *str = array[0];
    //这里的句号、逗号、引号等等都算在了长度里面。
    NSLog(@"~~~~~~~~~~~text:%@~~~~~~~length:%ld",str,str.length);
    NSMutableArray *numberArr = [NSMutableArray arrayWithCapacity:10];
    for (int i=0; i<array.count; i++) {
        NSString *text = array[i];
        NSString *textLength = [NSString stringWithFormat:@"%lu",(unsigned long)text.length];
        if ((unsigned long)text.length > 0) {
            [numberArr addObject:textLength];
        }
    }
    NSLog(@"所有字段的文字长度:%@",numberArr);

输入结果如下:

2018-11-29 14:48:35.512699+0800 Test1[21667:780226] ~~~~~~~~~~~text:###弗洛伦蒂诺·
阿里萨选择了这个时候向乌尔比诺的妻子费尔米娜·达萨表白了心迹,但是她被他的唐突,以及自己所
感到的内心深处触发出的情感所吓退~~~~~~~length:70
2018-11-29 14:48:35.513002+0800 Test1[21667:780226] 所有字段的文字长度:(
    70,
    38,
    60,
    37,
    47,
    20
)

二、正则表达式的切割

但是,实际场景是我们会以。、~、?、——等符号来判定为一句话。这样的话,我们如果还使用字符串的切割也可以,但是需要根据不同的符号遍历所有的数据,然后还要把数据拼接起来,这样的话整个步骤就显得非常的繁琐。于是,正则表达式就显示出它的优点了。
下面是正则表达式的处理方法:

    NSString *regexStr = @"(?<=?|。|###|,)(.*?)(?|。)";
    NSArray *regArr = [self matchString:textString toRegexString:regexStr];
    
    NSLog(@"~~~~~~~~~~regArr:%ld",regArr.count);
    for (int i=0; i<regArr.count; i++) {
        NSString *str = regArr[i];
        NSLog(@"分割之后的正则表达式的内容为:%@~~~~~~~~字数:%lu",regArr[i],(unsigned long)str.length);
    }
    

封装成类的的处理方式:

- (NSArray *)matchString:(NSString *)string toRegexString:(NSString *)regexStr
{    
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexStr options:NSRegularExpressionCaseInsensitive error:nil];
    
    NSArray * matches = [regex matchesInString:string options:0 range:NSMakeRange(0, [string length])];
    
    //match: 所有匹配到的字符,根据() 包含级
    NSMutableArray *array = [NSMutableArray array];
    for (NSTextCheckingResult *match in matches) {
        for (int i = 0; i < [match numberOfRanges]; i++) {
            //以正则中的(),划分成不同的匹配部分  这里会莫名其妙的遍历两次,导致输出两个
            相同的数据,我们可以像下面这样只取第一个值,也可以不进行遍历,直接取出来第一
            个值。
            NSLog(@"~~~~~~~~~~~~[match numberOfRanges]:%lu",(unsigned long)[match numberOfRanges]);
            if (i == 0) {
                NSString *component = [string substringWithRange:[match rangeAtIndex:i]];
                
                [array addObject:component];
            }

        }
    }
    
    return array;
}

我们使用 (?|。)打印输入内容,可以看到,都包含尾部的标点,如果我们使用(?=?|。)那么标点符号会被清除掉:

2018-11-29 15:05:21.338177+0800 Test1[21812:788917] 分割之后的正则表达式的内容为:
弗洛伦蒂诺·阿里萨选择了这个时候向乌尔比诺的妻子费尔米娜·达萨表白了心迹,但是她被他的唐突,
以及自己所感到的内心深处触发出的情感所吓退。~~~~~~~~字数:68
2018-11-29 15:05:21.338315+0800 Test1[21812:788917] 分割之后的正则表达式的内容为:当
他们都年轻的时候,她和弗洛伦蒂诺互相交换了许多炽热的情书,并且曾经决定结婚。~~~~~~~~字数
:39
2018-11-29 15:05:21.428182+0800 Test1[21812:788917] 分割之后的正则表达式的内容为:而
再次见到他时,费尔明娜却“惊慌地自问,怎么会如此残酷地让那样一个幻影在自己的心间占据了那么
长时间”,并对他说“忘了吧”。~~~~~~~~字数:61
2018-11-29 15:05:21.428674+0800 Test1[21812:788917] 分割之后的正则表达式的内容为:弗
洛伦蒂诺则珍守着对她的渴望,并且决心为她保持童贞直到他们最终能够走到一起。~~~~~~~~字数:
38
2018-11-29 15:05:21.428790+0800 Test1[21812:788917] 分割之后的正则表达式的内容为:然
而他很快发现自己用放纵的生活来排遣分离的空虚,费尔米娜嫁给了乌尔比诺医生?~~~~~~~~字数:
38
2018-11-29 15:05:21.428890+0800 Test1[21812:788917] 分割之后的正则表达式的内容为:成
为了他忠实的伴侣。~~~~~~~~字数:10
2018-11-29 15:05:21.428979+0800 Test1[21812:788917] 分割之后的正则表达式的内容为:而
医生本人也有着相似但比较简短的一段前事。~~~~~~~~字数:21

三、文字的变色

下面我们写一个示例来展示文字变色的处理过程:
使用定时器,定时获取数据,根据数据来判定需要变色的起始位置和范围。

        __block int i=0;
        [NSTimer scheduledTimerWithTimeInterval:2 repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSMutableAttributedString *mAttStr = [[NSMutableAttributedString alloc] initWithString:self.textString];

            //1、获取段落设置的全部内容
            for (NSString *key in [self.paragraphAttributes allKeys]) {
                NSValue *value = self.paragraphAttributes[key];
                [mAttStr addAttribute:key
                                value:value
                                range:NSMakeRange(0, self.textString.length)];
            }
            /*
             2、遍历取出来富文本参数数组内容(ConfigAttributedString对象的数组):
             1、addAttribute : 富文本属性
             2、value        : 富文本值
             3、range        : 富文本范围
             */
            for (int count = 0; count < _attributes.count; count++) {
                ConfigAttributedString *oneConfig = _attributes[count];
                [mAttStr addAttribute:oneConfig.attribute
                                value:oneConfig.value
                                range:oneConfig.range];
            }
            [mAttStr addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(10*i, 10)];
            self.textView.attributedText = mAttStr;
            ++i;

        }];

正则表达语法:https://www.jianshu.com/p/3323adcff24f
正则表达常见的使用:http://www.cnblogs.com/XYQ-208910/p/6056646.html

上一篇下一篇

猜你喜欢

热点阅读