iOS开发 -正则表达式的使用和匹配内容

我们经常会遇到验证一个用户的操作数据是否合法,我们最好的方式是用正则去检测用户的行为操作是否正确

来个图片放松一下啊
来个图片放松一下啊

正则匹配整数和浮点数

需求:检测文本中的数字,并改变颜色,数字都是序列化的样式文本:当前已经使用的存储
空间大小为3.2GB,下载文件占用788MB,还剩余6.7GB空间,总容量为12GB.
我们需要匹配出来一下几个数字
3.2GB 
788MB
6.7GB
12GB

我们如果第一眼看上去你觉得要如何去做呢,我们今天要的不仅是匹配,还要获取到对应的数值
这个匹配我们使用系统的NSRegularExpression ,进行内容的匹配,开始我想到了三种规则:如下

  1. \\d*\\.\\d*[M|G]B 这种规则只适合含有小数点的数值,等到项目中用的时候才发现整数没有匹配上去,继续修改下面
  2. (((\\d*\\.\\d*)MB)|((\\d*\\.\\d*)GB)) 这个是一位PHP大牛写的,我仔细分解了一下,似乎我写的那个就可以了,但是还是匹配到整数就错误。
  3. (\\d*(\\.\\d*)?)[M|G]B 这个才是我们想要的,既能匹配小数,又可以匹配整数,这个是我考虑之后稍作修改,检测结果是正常的

第三种情况的匹配代码实例如下:

    NSString *searchText = @"当前手机已使用存储大小为3.2GB,已下载文件占用899MB,剩余空间大小5.8GB,当前总容量为12GB";
    NSError *error = NULL;
    //@"\\d*\\.\\d*[M|G]B"   匹配字符串中连续规则的数字序列
    //@"(((\\d*\\.\\d*)MB)|((\\d*\\.\\d*)GB))"  匹配规则全部序列
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(\\d*(\\.\\d*)?)[M|G]B" 
    options:NSRegularExpressionCaseInsensitive error:&error];
    NSTextCheckingResult *result = [regex firstMatchInString:searchText options:0 range:NSMakeRange(0, [searchText length])];
    NSArray * matches1 = [regex matchesInString:searchText options:NSMatchingReportProgress range:NSMakeRange(0, [searchText length])];
    for (NSTextCheckingResult * test in matches1) {
       
        NSString *tagValuestr = [searchText substringWithRange:test.range];
         NSLog(@"tagvalue = %@",tagValuestr);
    }
    if (result) {
        NSLog(@"%@", [searchText substringWithRange:result.range]);
    }

控制台输出结果为:

2016-03-15 17:41:19.608 RegularExp[54814:2551313] tagvalue = 3.2GB
2016-03-15 17:41:19.608 RegularExp[54814:2551313] tagvalue = 899MB
2016-03-15 17:41:19.608 RegularExp[54814:2551313] tagvalue = 5.8GB
2016-03-15 17:41:19.608 RegularExp[54814:2551313] tagvalue = 12GB
2016-03-15 17:41:19.609 RegularExp[54814:2551313] 3.2GB

我们可以发现,这个就是我们想要的结果
result 是单个结果,使用matches是获取多个结果

我们再说一下获取URL参数的正则

代码如下:

 NSError *error1;
    NSString *regTags=[[NSString alloc] initWithFormat:@"(^|&|\\?)+%@=+([^&]*)(&|$)",@"adc"];
    NSRegularExpression *regex1 = [NSRegularExpression regularExpressionWithPattern:regTags
                                                                           options:NSRegularExpressionCaseInsensitive
                                                                             error:&error1];
    
    // 执行匹配的过程
     NSString *webaddress=@"http://www.baidu.com/dd/adb.htm?adc=e12&xx=lkw&dalsjd=12";
    NSArray *matches = [regex1 matchesInString:webaddress
                                      options:0
                                        range:NSMakeRange(0, [webaddress length])];
    for (NSTextCheckingResult *match in matches) {
        //NSRange matchRange = [match range];
        //NSString *tagString = [webaddress substringWithRange:matchRange];  // 整个匹配串
        //        NSRange r1 = [match rangeAtIndex:1];
        //        if (!NSEqualRanges(r1, NSMakeRange(NSNotFound, 0))) {    // 由时分组1可能没有找到相应的匹配,用这种办法来判断
        //            //NSString *tagName = [webaddress substringWithRange:r1];  // 分组1所对应的串
        //            return @"";
        //        }
        
        NSString *tagValue = [webaddress substringWithRange:[match rangeAtIndex:2]];  // 分组2所对应的串
        //    NSLog(@"分组2所对应的串:%@\n",tagValue);
        NSLog(@"tagvalue = %@",tagValue);
        
    }

控制台的输出

2016-03-15 17:41:19.609 RegularExp[54814:2551313] tagvalue = e12

以上是对NSRegularExpression 这个类的使用

下面我们扩展一些实用的东西:

方法一、 使用谓词NSPredicate创建正则表达式

一般我们只使用谓词仅供开发者判断用户输入的字符串是否合法,并没有其他要求

// 编写正则表达式:只能是数字或英文,或两者都存在
NSString *regex = @"^[a-z0-9A-Z]*$";
// 创建谓词对象并设定条件的表达式
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
// 判断的字符串
NSString *str = @"Hello100";
// 对字符串进行判断
if ([predicate evaluateWithObject:str]) {
    NSLog(@"Match");
}

上面判断之后的结果就是会输出 Match ,如果我们替换一下字符串为-、= ! 之类的,那么判断就不会进入。

方法二、 通过NSRegularExpression 获取指定的对象

我们可以过滤掉一些东西获取到我们想要的结果,代码更清晰:

NSString *url = @"8888@163.com";
NSError *error;
// 创建NSRegularExpression对象并指定正则表达式
NSRegularExpression *regex = [NSRegularExpression
                regularExpressionWithPattern:@"[^@]*\\."
                options:0
                error:&error];
if (!error) { // 如果没有错误
  // 获取特特定字符串的范围
  NSTextCheckingResult *match = [regex firstMatchInString:url
                          options:0
                            range:NSMakeRange(0, [url length])];
  if (match) {
    // 截获特定的字符串
    NSString *result = [url substringWithRange:match.range];
    NSLog(@"%@",result);
  }
} else { // 如果有错误,则把错误打印出来
  NSLog(@"error - %@", error);
}

上面这个列子我们是从特定字符串中检索以“@”开头 “.” 结尾的区间字符串,所以最终获取到的字符串结尾包括点“.”,最终输出的是“163.”;

方法三、NSRegularExpression 获取多个结果,也就是最上面我们的需求

我们讲解一个获取连续数字序列的正则

NSString *regex = @"\\-\\d*\\.";
NSString *str = @"-111.-666.-888.";
NSError *error;
NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:regex
                                                                         options:NSRegularExpressionCaseInsensitive
                                                                           error:&error];
// 对str字符串进行匹配
NSArray *matches = [regular matchesInString:str
                                    options:0
                                      range:NSMakeRange(0, str.length)];
// 遍历匹配后的每一条记录
for (NSTextCheckingResult *match in matches) {
    NSRange range = [match range];
    NSString *mStr = [str substringWithRange:range];
    NSLog(@"%@", mStr);
}

@"\\-\\d*\\.";我们这里的规则是-号开头,\ 代表特殊字符转义,不参与匹配,“\d” 相当于 [0-9] ,有\ 开始的规则,需要加入转义字符“、”
方法三的输出结果是

-111.
-666.
-888.

通过打印结果,我们可以得知,我们通过方法三的结果是多个,获取到我们想要的结果。

注:我们把常用的字符注释一下

  1. “\” :将下一个字符标记为一个特殊字符、或一个原义字符、或者一个向后引用,或者一个八进制转义符。例如:“\\n”匹配“\n” "\n"。序列“\\” 匹配“\” 而 “\(” 匹配“(”
  2. "^": 匹配输入字符串的开始位置,如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
  3. "$" : 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
  4. "*": 匹配前面的子表达式零次或多次(大于等于0次)。例如,zo*能匹配“z”,“zo”以及“zoo”。*等价于{0,}。
  5. "+":匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
  6. "?": 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”中的“do”。?等价于{0,1}。
  7. "{n}":n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
  8. "{n,}":n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
  9. "{n,m}":m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
  10. "?":当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。
  11. ".":匹配除“\r\n”之外的任何单个字符。要匹配包括“\r\n”在内的任何字符,请使用像“[\s\S]”的模式。
  12. "\s" :"匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。"

正则先说到这里,请查看链接:正则使用说明

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容