编码篇 - 正则表达式及其相关

前言

有时我们需要在一大段长文本中过滤出我们需要的字段,或者检验该文本是否符合要求(该文本是否是邮箱,链接,电话号码或身份证),这时候就需要用到正则表达式了,当然我们也可以使用 NSPredicate,这不重要,重要的是表达式对于刷选和逻辑判断来说是十分方便的。

文章脉络

谓词(NSPredicate)

Predicate(谓语)的意思。NSPredicate类是用来定义逻辑条件约束的获取或内存中的过滤搜索。原理和用法都类似于SQL中的where,作用相当于数据库的过滤取
NSPredicate真的是Cocoa的优势之一。其他语言的第三方库根本没法和他比。对于我们这些应用和框架开发者来说,有它作为标准组件使得我们在处理数据时有了很大的优势。

NSPredicate语法:

  • 比较运算符

=、==:判断两个表达式是否相等,在谓词中=和==是相同的意思都是判断,而没有赋值这一说

  NSNumber *testNumber = @123;
  NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF = 123"];
  if ([predicate evaluateWithObject:testNumber]) {
   NSLog(@"testString:%@", testNumber);
  }
  我们可以看到输出的内容为:
   2016-01-07 11:12:27.281 PredicteDemo[4130:80412] testString:123

=,=>:判断左边表达式的值是否大于或等于右边表达式的值
<=,=<:判断右边表达式的值是否小于或等于右边表达式的值
:判断左边表达式的值是否大于右边表达式的值
<:判断左边表达式的值是否小于右边表达式的值
!=、<>:判断两个表达式是否不相等
BETWEEN:BETWEEN表达式必须满足表达式 BETWEEN {下限,上限}的格式,要求该表达式必须大于或等于下限,并小于或等于上限
NSNumber *testNumber = @123;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF BETWEEN {100, 200}"];
if ([predicate evaluateWithObject:testNumber]) {
NSLog(@"testString:%@", testNumber);
} else {
NSLog(@"不符合条件");

  }
  输出结果为:
  2016-01-07 11:20:39.921 PredicteDemo[4366:85408] testString:123
  • 逻辑运算符

AND、&&:逻辑与,要求两个表达式的值都为YES时,结果才为YES。
NSArray *testArray = @[@1, @2, @3, @4, @5, @6];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF > 2 && SELF < 5"];
NSArray *filterArray = [testArray filteredArrayUsingPredicate:predicate];
NSLog(@"filterArray:%@", filterArray);
输出结果为:
2016-01-07 11:27:01.885 PredicteDemo[4531:89537] filterArray:(
3,
4
)
OR、||:逻辑或,要求其中一个表达式为YES时,结果就是YES
NOT、 !:逻辑非,对原有的表达式取反

  • 字符串比较运算符

BEGINSWITH:检查某个字符串是否以指定的字符串开头(如判断字符串是否以a开头:BEGINSWITH 'a')
ENDSWITH:检查某个字符串是否以指定的字符串结尾
CONTAINS:检查某个字符串是否包含指定的字符串
LIKE:检查某个字符串是否匹配指定的字符串模板。其之后可以跟?代表一个字符和代表任意多个字符两个通配符。比如"name LIKE 'ac'",这表示name的值中包含ac则返回YES;"name LIKE '?ac'",表示name的第2、3个字符为ac时返回YES。

MATCHES:检查某个字符串是否匹配指定的正则表达式。虽然正则表达式的执行效率是最低的,但其功能是最强大的,也是我们最常用的。所以NSPredicate也可以结合正则表达式语句来使用。

注:字符串比较都是区分大小写和重音符号的。如:café和cafe是不一样的,Cafe和cafe也是不一样的。如果希望字符串比较运算不区分大小写和重音符号,请在这些运算符后使用[c],[d]选项。其中[c]是不区分大小写,[d]是不区分重音符号,其写在字符串比较运算符之后,比如:name LIKE[cd] 'cafe',那么不论name是cafe、Cafe还是café上面的表达式都会返回YES。

  • 集合运算符

ANY、SOME:集合中任意一个元素满足条件,就返回YES。
ALL:集合中所有元素都满足条件,才返回YES。
NONE:集合中没有任何元素满足条件就返回YES。如:NONE person.age < 18,表示person集合中所有元素的age>=18时,才返回YES。
IN:等价于SQL语句中的IN运算符,只有当左边表达式或值出现在右边的集合中才会返回YES。我们通过一个例子来看一下
NSArray *filterArray = @[@"ab", @"abc"];
NSArray *array = @[@"a", @"ab", @"abc", @"abcd"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", filterArray];
NSLog(@"%@", [array filteredArrayUsingPredicate:predicate]);
代码的作用是将array中和filterArray中相同的元素去除,输出为:
2016-01-07 13:17:43.669 PredicteDemo[6701:136206] (
a,
abcd
)
array[index]:返回array数组中index索引处的元素
array[FIRST]:返回array数组中第一个元素
array[LAST]:返回array数组中最后一个元素
array[SIZE]:返回array数组中元素的个数

  • 直接量

在谓词表达式中可以使用如下直接量
FALSE、NO:代表逻辑假
TRUE、YES:代表逻辑真
NULL、NIL:代表空值
SELF:代表正在被判断的对象自身
"string"或'string':代表字符串
数组:和c中的写法相同,如:{'one', 'two', 'three'}。
数值:包括证书、小数和科学计数法表示的形式
十六进制数:0x开头的数字
八进制:0o开头的数字
二进制:0b开头的数字

谓词的用法

  • 构造谓词 使用正则表达式进行判断
    evaluateWithObject:方法返回的是一个BOOL值,如果符合条件就返回YES,不符合就返回NO。
    # 有人说 只有在正则表达式为^表达式$时使用谓词才是准确的,而不是所有情况都使用。
    # 其他情况下会出现判断错误的情况,未亲测,有待研究

  • 使用谓词过滤集合
    # 我想这应该是 NSPredicate 最重要最强大的用处了,

          对于集合中的条件刷选,我们一般使用 for循环,新建容器,
         if else 找出目标元素装入新的容器中。而 NSPredicate  可以使用简洁的语句就实现如此繁琐的操作,
          的确是省事了不少
    
       NSArray提供了如下方法使用谓词来过滤集合
    - (NSArray*)filteredArrayUsingPredicate:(NSPredicate *)predicate:使用指定的谓词过滤NSArray集合,返回符合条件的元素组成的新集合
    
        NSMutableArray提供了如下方法使用谓词来过滤集合
    - (void)filterUsingPredicate:(NSPredicate *)predicate:使用指定的谓词过滤NSMutableArray,剔除集合中不符合条件的元素
    
        NSSet提供了如下方法使用谓词来过滤集合
     - (NSSet*)filteredSetUsingPredicate:(NSPredicate *)predicate NS_AVAILABLE(10_5, 3_0):作用同NSArray中的方法
    
        NSMutableSet提供了如下方法使用谓词来过滤集合
    - (void)filterUsingPredicate:(NSPredicate *)predicate NS_AVAILABLE(10_5, 3_0):作用同NSMutableArray中的方法。
    
  • 在谓词中使用占位符参数
    %K:用于动态传入属性名
    %@:用于动态设置属性值
    详细用法查看这里

常用 NSPredicate 实例

  • 正则判断手机号码地址格式
    # 手机运营商的号码有可能添加新号段,所以这样的验证方式还是不稳妥的

    - (BOOL)isMobileNumber:(NSString *)mobileNum
    {
      /**
       * 手机号码
       * 移动:134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188
       * 联通:130,131,132,152,155,156,185,186
       * 电信:133,1349,153,180,189
       */
      NSString * MOBILE = @"^1(3[0-9]|5[0-35-9]|8[025-9])\\d{8}$";
      /**
       10         * 中国移动:China Mobile
       11         * 134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188
       12         */
      NSString * CM = @"^1(34[0-8]|(3[5-9]|5[017-9]|8[278])\\d)\\d{7}$";
      /**
       15         * 中国联通:China Unicom
       16         * 130,131,132,152,155,156,185,186
       17         */
      NSString * CU = @"^1(3[0-2]|5[256]|8[56])\\d{8}$";
      /**
       20         * 中国电信:China Telecom
       21         * 133,1349,153,180,189
       22         */
      NSString * CT = @"^1((33|53|8[09])[0-9]|349)\\d{7}$";
      /**
       25         * 大陆地区固话及小灵通
       26         * 区号:010,020,021,022,023,024,025,027,028,029
       27         * 号码:七位或八位
       28         */
      // NSString * PHS = @"^0(10|2[0-5789]|\\d{3})\\d{7,8}$";
      
      NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE];
      NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM];
      NSPredicate *regextestcu = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CU];
      NSPredicate *regextestct = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CT];
      
      if (([regextestmobile evaluateWithObject:mobileNum] == YES)
          || ([regextestcm evaluateWithObject:mobileNum] == YES)
          || ([regextestct evaluateWithObject:mobileNum] == YES)
          || ([regextestcu evaluateWithObject:mobileNum] == YES))
      {
          if([regextestcm evaluateWithObject:mobileNum] == YES) {
              NSLog(@"China Mobile");
          } else if([regextestct evaluateWithObject:mobileNum] == YES) {
              NSLog(@"China Telecom");
          } else if ([regextestcu evaluateWithObject:mobileNum] == YES) {
              NSLog(@"China Unicom");
          } else {
              NSLog(@"Unknow");
          }
          
          return YES;
      }
      else
      {
          return NO;
      }
    }
     # 简化版
     - (BOOL)checkPhoneNumber:(NSString *)phoneNumber
    {
      NSString *regex = @"^[1][3-8]\\d{9}$";
      NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
      return [pred evaluateWithObject:phoneNumber];
    }
    
  • 验证email

    +(BOOL)isValidateEmail:(NSString *)email {
    
      NSString *strRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{1,5}";
       #或者这个NSString *regex = @"\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
      NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", strRegex];
      return [predicate evaluateWithObject:email];  
    }
    
  • 验证电话号码
    +(BOOL)isValidateTelNumber:(NSString *)number {

      NSString *strRegex = @"[0-9]{1,20}";
      NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", strRegex];
      return [predicate evaluateWithObject:number];   
    }
    

NSRegularExpression 正则表达式

RegularExpression 的汉语意思就是正则表达式,所以 NSRegularExpression 才是iOS中的正则表达式, 不熟悉的人会错误地以为NSPredicate 是正则表达式。下面介绍一下 NSRegularExpression


NSRegularExpression 位于 Foundation 框架中,主要作用相当与检索条件判断,但是其强大方便的功能是以晦涩的语法为牺牲的。如果你想仔细研究的话,可以看这俩篇文章:语法列表& 入门教程
如果你看哭了,不要找我,/笑哭

正则表达式最主要的作用是查找刷选、或者替换,当然也可以用来做判断。numberOfMatchesInString 为0就是没有一个匹配的目标,也就是 NO 。

NSRegularExpression 的相关方法

  # 初始化方法
  + (nullable NSRegularExpression *)regularExpressionWithPattern:(NSString *)pattern options:(NSRegularExpressionOptions)options error:(NSError **)error;
  - (nullable instancetype)initWithPattern:(NSString *)pattern options:(NSRegularExpressionOptions)options error:(NSError **)error NS_DESIGNATED_INITIALIZER;

  #  操作方法
   返回所有匹配结果的集合(适合,从一段字符串中提取我们想要匹配的所有数据) 
  - (NSArray<NSTextCheckingResult *> *)matchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range; 
   返回正确匹配的个数(通过等于0,来验证邮箱,电话什么的,代替NSPredicate) 
  - (NSUInteger)numberOfMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range; 
   返回第一个匹配的结果。注意,匹配的结果保存在  NSTextCheckingResult 类型中 
   - (NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range; 
    返回第一个正确匹配结果字符串的NSRange 
  - (NSRange)rangeOfFirstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range; 
    block方法 枚举每个符合约定的字段,通过block对其进行操作 
 - (void)enumerateMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range usingBlock:(void (^)(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop))block; 
 */  


 # NSRegularExpression类中提供了方法来实现用新的字段来替换原文中符合规则的字段。

   用新字段替换原文本中的对应字段,并返回操作后的NSString
 - (NSString *)stringByReplacingMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)templ;
   用新字段替换原文本中的对应字段,并返回操作次数(替换字段的个数)
 - (NSUInteger)replaceMatchesInString:(NSMutableString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)templ;
  

 # NSRegularExpressionOptions;

 NSRegularExpressionCaseInsensitive             = 1 << 0,   // 不区分大小写的 
 NSRegularExpressionAllowCommentsAndWhitespace  = 1 << 1,   // 忽略空格和# - 
 NSRegularExpressionIgnoreMetacharacters        = 1 << 2,   // 整体化 
 NSRegularExpressionDotMatchesLineSeparators    = 1 << 3,   // 匹配任何字符,包括行分隔符 
 NSRegularExpressionAnchorsMatchLines           = 1 << 4,   // 允许^和$在匹配的开始和结束行 
 NSRegularExpressionUseUnixLineSeparators       = 1 << 5,   // (查找范围为整个的话无效) 
 NSRegularExpressionUseUnicodeWordBoundaries    = 1 << 6    // (查找范围为整个的话无效) 
 }; 

 #  NSTextCheckingResult    这是一个文本搜索结果对象里面包含了 Range 属性 和一个文本搜索类型  的属性,
  我们只需要使用 Range 属性 即可.
  [@"原文本" substringWithRange:range]] 即可获取匹配到的内容
Paste_Image.png

示例

# 测试字符串,把里面的电话号码解析出来  
NSString *urlString = @"哈哈哈哈呵呵呵s15279107723在这里啊啊啊啊s15279107716";  
NSError *error = NULL;  
// 根据匹配条件,创建了一个正则表达式(类方法,实例方法类似)  
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\d{3}-\\d{8}|\\d{3}-\\d{7}|\\d{4}-\\d{8}|\\d{4}-\\d{7}|1+[358]+\\d{9}|\\d{8}|\\d{7}"   options:NSRegularExpressionCaseInsensitive error:&error];  
if (regex != nil) {  
    NSTextCheckingResult *firstMatch = [regex firstMatchInString:urlString  
                                                         options:0  
                                                        range:NSMakeRange(0, [urlString length])];  
    if (firstMatch) {  
        NSRange resultRange = [firstMatch rangeAtIndex:0];  
        //从urlString中截取数据  
        NSString *result = [urlString substringWithRange:resultRange];  
        NSLog(@"result = %@",result);  
    }  

    NSUInteger number = [regex numberOfMatchesInString:urlString  
                                               options:0  
                                               range:NSMakeRange(0, [urlString length])];  
    NSLog(@"number = %ld",number);  

    [regex enumerateMatchesInString:urlString options:0 range:NSMakeRange(0, [urlString length]) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOLBOOL *stop) {  
        NSLog(@"---%@",NSStringFromRange([result range]));  
        if (flags != NSMatchingInternalError) {  
            NSRange firstHalfRange = [result rangeAtIndex:0];  
            if (firstHalfRange.length > 0) {  
                NSString *resultString1 = [urlString substringWithRange:firstHalfRange];  
                NSLog(@"result1 = %@",resultString1);  
            }  
        }  
        *stop = YES;  
    }];  
}  

需要注意的地方

有些正则表达式 在转化成字符串时就有出编译警告,对元字符需要转译,比如下面这个验证邮箱的正则表达式:

   \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
   NSString *regex = @"\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";

常用正则表达式

(1)^和$属于特殊符号,前者表示匹配字符串的开头,后者表示匹配字符串的结尾。
(2)得出.符号表示任一字符(除换行符之外)。
(3)还有\d用来表示任意的单个数字,\w表示任意一个字母或数字或者直接使用0-9的任意数字表示具体数字。而特殊符号?表示前一个字符为0或者1个。
(4)表达式的字符分为两类:值表达和修饰表达。所谓值表达就是说这个符号表示了某个值,就像\d表示数字,.表示任意非换行符字符。修饰表达用来修饰值达成某种条件,比如{2}表示前面一个值重复两次,*表示前一个值重复0次或者更多次。
结合例子解释正则表达式

单语法/字符说明表
值表达

语法 意义
. 匹配除换行符外的任意字符
\w 匹配字母或者数字的字符
\W 匹配任意不是字母或数字的字符
\s 匹配任意的空白符(空格、制表符、换行符)
\S 匹配任意不是空白符的字符
\d 匹配任意数字
\D 匹配任意非数字的字符
\b 匹配单词的结尾或者开头的字符
\B 匹配任意不是单词结尾或开头的字符
[^x] 匹配任意非x的字符。如[^[a-z]]匹配非小写字母的任意字符
^ 匹配字符串的开头
$ 匹配字符串的结尾

修饰表达

语法 意义
* 匹配重复任意次数
+ 匹配重复一次以上的次数
? 匹配一次或零次
{n} 匹配重复n次
{n,} 匹配重复n次或n次以上
{n,m} 匹配重复最少n次最多m次

除了这些常见的,想了解更多可以查阅文章上面推荐的一篇语法文章。

以下是摘自一位作者的总结,感觉很不错,就拿来用了,出自此处

一、校验数字的表达式

  • 数字:^[0-9]*$
  • n位的数字:^\d{n}$
  • 至少n位的数字:^\d{n,}$
  • m-n位的数字:^\d{m,n}$
  • 零和非零开头的数字:^(0|[1-9][0-9]*)$
  • 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
  • 带1-2位小数的正数或负数:^(-)?\d+(.\d{1,2})?$
  • 正数、负数、和小数:^(-|+)?\d+(.\d+)?$
  • 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
  • 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
  • 非零的正整数:^[1-9]\d$ 或 ^([1-9][0-9]){1,3}$ 或 ^+?[1-9][0-9]*$
  • 非零的负整数:^-[1-9][]0-9″$ 或 ^-[1-9]\d$
  • 非负整数:^\d+$ 或 ^[1-9]\d*|0$
  • 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
  • 非负浮点数:^\d+(.\d+)?$ 或 ^[1-9]\d.\d|0.\d[1-9]\d|0?.0+|0$
  • 非正浮点数:^((-\d+(.\d+)?)|(0+(.0+)?))$ 或 ^(-([1-9]\d.\d|0.\d[1-9]\d))|0?.0+|0$
  • 正浮点数:^[1-9]\d.\d|0.\d[1-9]\d$ 或 ^(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9]))$
  • 负浮点数:^-([1-9]\d.\d|0.\d[1-9]\d)$ 或 ^(-(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9])))$
  • 浮点数:^(-?\d+)(.\d+)?$ 或 ^-?([1-9]\d.\d|0.\d[1-9]\d|0?.0+|0)$

二、校验字符的表达式

  • 汉字:^[\u4e00-\u9fa5]{0,}$
  • 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
  • 长度为3-20的所有字符:^.{3,20}$
  • 由26个英文字母组成的字符串:^[A-Za-z]+$
  • 由26个大写英文字母组成的字符串:^[A-Z]+$
  • 由26个小写英文字母组成的字符串:^[a-z]+$
  • 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
  • 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
  • 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
  • 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
  • 可以输入含有%&’,;=?$\”等字符:[%&’,;=?$\x22]+
  • 禁止输入含有~的字符:[^%&’,;=?$\x22]+

三、特殊需求表达式

  • Email地址:^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$
  • 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
  • InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+.)+[\w-]+(/[\w-./?%&=]*)?$?%24)
  • 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
  • 电话号码(“XXX-XXXXXXX”、”XXXX-XXXXXXXX”、”XXX-XXXXXXX”、”XXX-XXXXXXXX”、”XXXXXXX”和”XXXXXXXX):^((\d{3,4}-)|\d{3.4}-)?\d{7,8}$
  • 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
  • 身份证号(15位、18位数字):^\d{15}|\d{18}$
  • 短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
  • 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
  • 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
  • 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}$
  • 日期格式:^\d{4}-\d{1,2}-\d{1,2}
  • 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
  • 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
  • 钱的输入格式:
    • 有四种钱的表示形式我们可以接受:”10000.00” 和 “10,000.00”, 和没有 “分” 的 “10000” 和 “10,000”:^[1-9][0-9]*$
    • .这表示任意一个不以0开头的数字,但是,这也意味着一个字符”0″不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
    • .一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
    • .这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
  • .必须说明的是,小数点后面至少应该有1位数,所以”10.”是不通过的,但是 “10” 和 “10.2” 是通过的:^[0-9]+(.[0-9]{2})?$
  • 这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$22 7.这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})(.[0-9]{1,2})?$23 8.1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3}))(.[0-9]{1,2})?$
  • 备注:这就是最终结果了,别忘了”+”可以用”*”替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里
  • xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+.[x|X][m|M][l|L]$
  • 中文字符的正则表达式:[\u4e00-\u9fa5]
  • 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
  • 空白行的正则表达式:\n\s*\r (可以用来删除空白行)
  • HTML标记的正则表达式:<(\S?){FNXX==XXFN}>.?|<.? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)
  • 首尾空白字符的正则表达式:\s*|\s*$或(\s)|(\s$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
  • 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
  • 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
  • IP地址:\d+.\d+.\d+.\d+ (提取IP地址时有用)
  • 固定电话
    ^0\d{2}-?\d{8}$
    不管是010-88888888,还是02098989898都能进行正确匹配。
  • 密码应该包括一个或以上的大写字母以及小写字母
    (.*[A-Z]+.*[a-z]+.*$|.[a-z]+.[A-Z]+.*$)

小结

这算是一篇科普类文章,对自己来说也是一个笔记,以后用到相关的知识可以来此查看,中间引用了其他作者的作品,再次表示感谢,同时也文中也有指明出处。后续会持续更新新的使用方法。(未完 待续........)

参考文章
iOS中的谓词(NSPredicate)使用
正则表达式 NSRegularExpression

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

推荐阅读更多精彩内容