精品文章正则表达式iOS技术专题

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

2016-03-15  本文已影响1117人  Raybon_lee

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

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

正则匹配整数和浮点数

需求:检测文本中的数字,并改变颜色,数字都是序列化的样式文本:当前已经使用的存储
空间大小为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]。"

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

上一篇下一篇

猜你喜欢

热点阅读