iOS之正则表达式的使用和谓词(NSPredicate)的使用(三)

时间:2022-08-30 18:49:17

正则表达式匹配返回的是一个范围,用这个范围去原来的字符串截取,就得到我们想要的字符串;


1.=========字符串匹配


NSString *phoneNo =@"13143503442";

NSRange range = [phoneNorangeOfString:@"^1[3]\\d{9}$ options:NSRegularExpressionSearch];//返回在phoneNo中字符串的位置

if (range.location != NSNotFound) {

    NSLog(@"%@", [phoneNo substringWithRange:range]);

}

       rangeOfString:options:会返回一个NSRange,用来接收匹配的范围,当匹配不到结果时,将会返回一个NSIntegerMax最大值,也就是NSNotFound,因此我们可以用它来判断用户输入的内容是否符合规则。

2.============//NSRegularExpression类创建正则表达式-----匹配第一个结果字符串

    NSString *url =@"123456789@qq.com";

    NSError *error;

    // 创建NSRegularExpression对象并指定正则表达式

    NSRegularExpression *regex = [NSRegularExpression

                                  regularExpressionWithPattern:@"[^@]*\\."

                                  options:0

                                  error:&error];

    if (!error) {//如果没有错误

        // 获取特特定字符串的范围 match.range----抓取了第一个结果

        NSTextCheckingResult *match = [regexfirstMatchInString:url

                                                        options:0

                                                          range:NSMakeRange(0, [url length])];

        if (match) {

            // 截获特定的字符串

            NSString *result = [urlsubstringWithRange:match.range];

            NSLog(@"%@",result);

        }

    } else {//如果有错误,则把错误打印出来

        NSLog(@"error - %@", error);

    }

   //这个例子是从字符串里检索出以“@”开头“.”结尾的区间字符串,最后检索出来的字符串结尾包括“.”,因此此例子最终输出结果为“qq.”


3.==============//NSRegularExpression类之抓取多个结果

    

   //当一个字符串有多个符合特定规则的字符,我们可以分别获取到符合特定规则的字符:

    NSString *regex =@"\\-\\d*\\.";

    NSString *str =@"-34023242.-34203020.";

    NSError *error;

    NSRegularExpression *regular = [NSRegularExpressionregular ExpressionWithPattern:regex

                                                                            options:NSRegularExpressionCaseInsensitive

                                                                              error:&error];

    // str字符串进行匹配----把匹配到的字符串全部放入数组,数组中的对象是NSTextCheckingResult

    NSArray *matches = [regularmatchesInString:str

                                        options:0

                                          range:NSMakeRange(0, str.length)];

    // 遍历匹配后的每一条记录

    for (NSTextCheckingResult *matchin matches) {

        NSRange range = [matchrange];

        NSString *mStr = [strsubstringWithRange:range];

        NSLog(@"%@", mStr);

    }




参考:http://www.jb51.net/tools/zhengze.html

4.============正则表达式中符号的解释

表1.常用的元字符
代码 说明
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束,\b开始并且\b结束的就时一个单词;
^ 匹配字符串的开始
$ 匹配字符串的结束



                                                                             表2.常用的限定符
代码/语法 说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次,就是?前面的字符可以存在一次,也可以不存在
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次


                        表2 中的符号是针对仅临它的前一个字符



**************[ ]--------------方括号匹配单个字符;匹配方括号中的一个字符*****************


[aeiou]就匹配任何一个英文元音字母

[.?!]匹配标点符号(.或?或!)

我们也可以指定一个字符范围,像[0-9]代表的含意与\d就是完全一致的:一位数字

同理[a-z0-9A-Z_]也完全等同于\w(如果只考虑英文的话);

***********字符转义 \  **************

\\----------  \

\*----------  *

\(----------  (

\.----------  .


************或 |  **************|两边的先各自匹配,最后在匹配 |;

   x|y:匹配x或y。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”则匹配“zood”或“food”。


***************括号( )**************

(\d{1,3}\.){3}\d{1,3}是一个简单的IP地址匹配表达式;(\d{1,3}\.){3}匹配一到三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字(\d{1,3})。


**************************反义****************

\W匹配任意不是字母,数字,下划线,汉字的字符
\S匹配任意不是空白符的字符
\D匹配任意非数字的字符
\B匹配不是单词开头或结束的位置
[^x]匹配除了x以外的任意字符

[^aeiou]匹配除了aeiou这几个字母以外的任意字符


******************分组向后引用************************

使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。

后向引用用于重复搜索前面某个分组匹配的文本。例如,\1代表分组1匹配的文本。难以理解?请看示例:

\b(\w+)\b\s+\1\b可以用来匹配重复的单词,像go go, 或者kitty kitty。这个表达式首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字(\b(\w+)\b),这个单词会被捕获到编号为1的分组中,然后是1个或几个空白符(\s+),最后是分组1中捕获的内容(也就是前面匹配的那个单词)(\1)。

你也可以自己指定子表达式的组名。要指定一个子表达式的组名,请使用这样的语法:(?<Word>\w+)(或者把尖括号换成'也行:(?'Word'\w+)),这样就把\w+的组名指定为Word了。要反向引用这个分组捕获的内容,你可以使用\k<Word>,所以上一个例子也可以写成这样:\b(?<Word>\w+)\b\s+\k<Word>\b

使用小括号的时候,还有很多特定用途的语法。下面列出了最常用的一些:

表4.常用分组语法
分类 代码/语法 说明
捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
零宽断言 (?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
注释 (?#comment) 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读




表7.尚未详细讨论的语法
代码/语法 说明
\a 报警字符(打印它的效果是电脑嘀一声)
\b 通常是单词分界位置,但如果在字符类里使用代表退格
\t 制表符,Tab
\r 回车
\v 竖向制表符
\f 换页符
\n 换行符
\e Escape
\0nn ASCII代码中八进制代码为nn的字符
\xnn ASCII代码中十六进制代码为nn的字符
\unnnn Unicode代码中十六进制代码为nnnn的字符
\cN ASCII控制字符。比如\cC代表Ctrl+C
\A 字符串开头(类似^,但不受处理多行选项的影响)
\Z 字符串结尾或行尾(不受处理多行选项的影响)
\z 字符串结尾(类似$,但不受处理多行选项的影响)
\G 当前搜索的开头
\p{name} Unicode中命名为name的字符类,例如\p{IsGreek}
(?>exp) 贪婪子表达式
(?<x>-<y>exp) 平衡组
(?im-nsx:exp) 在子表达式exp中改变处理选项
(?im-nsx) 为表达式后面的部分改变处理选项
(?(exp)yes|no) 把exp当作零宽正向先行断言,如果在这个位置能匹配,使用yes作为此组的表达式;否则使用no
(?(exp)yes) 同上,只是使用空表达式作为no
(?(name)yes|no) 如果命名为name的组捕获到了内容,使用yes作为表达式;否则使用no
(?(name)yes) 同上,只是使用空表达式作为no

==============谓词(NSPredicate)==================

只要我们使用谓词(NSPredicate)都需要为谓词定义谓词表达式,而这个表达式必须是一个返回BOOL的值。

谓词表达式由表达式、运算符和值构成。


1.===============evaluateWithObject:是否有匹配的,返回BOOL

    NSString *regex =@"^[0-9]*$";//正则匹配小数

    NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];

    BOOL isMatch = [pred evaluateWithObject:@"99999"];//是否有匹配pre的,有返回YES,没有匹配返回NO

    NSLog(@"--result---%d",isMatch);


2.==========

1.***********比较运算符

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

NSNumber *testNumber = @123;

NSPredicate *predicate = [NSPredicatepredicateWithFormat:@"SELF = 123"];

if ([predicate evaluateWithObject:testNumber]) {//YES

    NSLog(@"testString:%@", testNumber);

}

>==>:判断左边表达式的值是否大于或等于右边表达式的值

<==<:判断右边表达式的值是否小于或等于右边表达式的值

>:判断左边表达式的值是否大于右边表达式的值

<:判断左边表达式的值是否小于右边表达式的值

!=<>:判断两个表达式是否不相等

BETWEENBETWEEN表达式必须满足表达式 BETWEEN {下限,上限}的格式,要求该表达式必须大于或等于下限,并小于或等于上限

NSNumber *testNumber = @123;

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF BETWEEN {100, 200}"];

if ([predicate evaluateWithObject:testNumber]) {

    NSLog(@"testString:%@", testNumber);

} else {

    NSLog(@"不符合条件");

}

2.*************逻辑运算符


AND&&:逻辑与,要求两个表达式的值都为YES时,结果才为YES

NSArray *testArray = @[@1,@2,@3,@4,@5,@6];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF > 2 && SELF < 5"];

NSArray *filterArray = [testArrayfilteredArrayUsingPredicate:predicate];//过滤数组后得到新的数组

NSLog(@"filterArray:%@", filterArray);//结果为:filterArray:(3,4)


OR||:逻辑或,要求其中一个表达式为YES时,结果就是YES

NOT !:逻辑非,对原有的表达式取反


3.******************字符串比较运算符


BEGINSWITH:检查某个字符串是否以指定的字符串开头(如判断字符串是否以a开头:BEGINSWITH'a'

ENDSWITH:检查某个字符串是否以指定的字符串结尾

CONTAINS:检查某个字符串是否包含指定的字符串

LIKE:检查某个字符串是否匹配指定的字符串模板。其之后可以跟?代表一个字符通配和*代表任意多个字符通配符。比如"name LIKE '*ac*'",这表示name的值中包含ac则返回YES"name LIKE '?ac*'",表示name的第23个字符为ac时返回YES

MATCHES:检查某个字符串是否匹配指定的正则表达式。虽然正则表达式的执行效率是最低的,但其功能是最强大的,也是我们最常用的。例如:上面的例子1;

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

除了IN 之外 BETWEEN可以获取一定范围的值示例代码如下  

    NSArray *array1 = [NSArray arrayWithObjects:@100,@20,@3,@4,@4,@6,@7,@1,nil]

    

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF BETWEEN{1,20}"];

    NSArray *temp = [array1 filteredArrayUsingPredicate:predicate];

    

-------

 

同时还有以下与字符串操作相关的关键词


BEGINSWITH  :以某个字符串开头


ENDSWITH     :以某个字符串结尾


CONTAINS      :是否包含某个字符串


同时这三个关键词后面还可以跟上一些格式符号如:BEGINSWITH[cd] c表示不区分大小写 d表示不区分发音符号 cd就可以表示即不区分大小写也不区分发音符号

    

    NSArray *array1 = [NSArray arrayWithObjects:@"jack",@"anne",@"reserved",@"control" ,@"type",@"soure",@"version",nil];

    

    //查询出包含e这个字符的字符串

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] 'E' "];

    

    NSArray *temp = [array1 filteredArrayUsingPredicate:predicate];

   ---------

一个你可能会用到的关键字 LIKE 他后面也可以写[cd]格式符号


    NSArray *array1 = [NSArray arrayWithObjects:@"jack",@"anne",@"reserved",@"control" ,@"type",@"soure",@"version",nil];

    

    //查询出包含e这个字符的字符串

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF like[cd] '*e*' "];//*表示通配符

    

    NSArray *temp = [array1 filteredArrayUsingPredicate:predicate];

 

4.*******************集合运算符


ANYSOME:集合中任意一个元素满足条件,就返回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(@"%@", [arrayfilteredArrayUsingPredicate:predicate]);

代码的作用是将array中和filterArray中相同的元素去除,输出为:(a,abcd)

array[index]:返回array数组中index索引处的元素

array[FIRST]:返回array数组中第一个元素

array[LAST]:返回array数组中最后一个元素

array[SIZE]:返回array数组中元素的个数


5.*****************直接量


在谓词表达式中可以使用如下直接量


FALSENO:代表逻辑假

TRUEYES:代表逻辑真

NULLNIL:代表空值

SELF:代表正在被判断的对象自身

"string"'string':代表字符串

数组:和c中的写法相同,如:{'one','two','three'}

数值:包括证书、小数和科学计数法表示的形式

十六进制数:0x开头的数字

八进制:0o开头的数字

二进制:0b开头的数字

6.********************保留字


下列单词都是保留字(不论大小写)


ANDORINNOTALLANYSOMENONELIKECASEINSENSITIVECIMATCHESCONTAINSBEGINSWITHENDSWITHBETWEENNULLNILSELFTRUEYESFALSENOFIRSTLASTSIZEANYKEYSUBQUERYCASTTRUEPREDICATEFALSEPREDICATE


注:虽然大小写都可以,但是更推荐使用大写来表示这些保留字


7.============数组的过滤方法:
  • 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中的方法。

通过上面的描述可以看出,使用谓词过滤不可变集合和可变集合的区别是:过滤不可变集合时,会返回符合条件的集合元素组成的新集合;过滤可变集合时,没有返回值,会直接剔除不符合条件的集合元素

8.========================= 在谓词中使用占位符参数

@implementation ZLPersonModel

- (instancetype)initWithName:(NSString *)name age:(NSUInteger)age sex:(ZLPersonSex)sex
{
if (self = [super init]) {
_name = name;
_age = age;
_sex = sex;
}
return self;
}

+ (instancetype)personWithName:(NSString *)name age:(NSUInteger)age sex:(ZLPersonSex)sex
{
return [[self alloc] initWithName:name age:age sex:sex];
}

- (NSString *)description
{
return [NSString stringWithFormat:@"[name = %@, age = %ld, sex = %ld]", self.name, self.age, self.sex];
}
@end



首先如果我们想在谓词表达式中使用变量,那么我们需要了解下列两种占位符:


%K:用于动态传入属性名

%@:用于动态设置属性值

其实相当于变量名与变量值


除此之外,还可以在谓词表达式中使用动态改变的属性值,就像环境变量一样

NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF CONTAINS $VALUE"];

上述表达式中,$VALUE是一个可以动态变化的值,它其实最后是在字典中的一个key,所以可以根据你的需要写不同的值,但是必须有$开头,随着程序改变$VALUE这个谓词表达式的比较条件就可以动态改变。


下面我们通过一个例子来看看这三个重要的占位符应该如何使用:

NSArray *array = @[[ZLPersonModel personWithName:@"Jack" age:20 sex:ZLPersonSexMale],

               [ZLPersonModel personWithName:@"Rose" age:22 sex:ZLPersonSexFamale],

               [ZLPersonModel personWithName:@"Jackson" age:30 sex:ZLPersonSexMale],

               [ZLPersonModel personWithName:@"Johnson" age:35 sex:ZLPersonSexMale]];

//  定义一个property来存放属性名,定义一个value来存放值

NSString *property = @"name";

NSString *value = @"Jack";

//  该谓词的作用是如果元素中property属性含有值value时就取出放入新的数组内,这里是name包含Jack

NSPredicate *pred = [NSPredicatepredicateWithFormat:@"%K CONTAINS %@",property,value];

NSArray *newArray = [array filteredArrayUsingPredicate:pred];

NSLog(@"newArray:%@", newArray);

输出为

 newArray:(

                         "[name = Jack, age = 20, sex = 0]",

                         "[name = Jackson, age = 30, sex = 0]"

                                                             )


//  创建谓词,属性名改为age,要求这个age包含$VALUE字符串

NSPredicate *predTemp = [NSPredicatepredicateWithFormat:@"%K > $VALUE",@"age"];

// 指定$SUBSTR的值为 25   这里注释中的$SUBSTR改为$VALUE

NSPredicate *pred1 = [predTemppredicateWithSubstitutionVariables:@{@"VALUE" :@25}];

NSArray *newArray1 = [array filteredArrayUsingPredicate:pred1];

NSLog(@"newArray1:%@", newArray1);

 输出为newArray1:(

              "[name = Jackson, age = 30, sex = 0]",

              "[name = Johnson, age = 35, sex = 0]"

                                                              )



//  修改 $SUBSTR的值为32 这里注释中的SUBSTR改为$VALUE

NSPredicate *pred2 = [predTemppredicateWithSubstitutionVariables:@{@"VALUE" :@32}];

NSArray *newArray2 = [array filteredArrayUsingPredicate:pred2];

NSLog(@"newArray2:%@", newArray2);

输出为newArray2:(

                     "[name = Johnson, age = 35, sex = 0]"

                                                              )