正则表达式匹配返回的是一个范围,用这个范围去原来的字符串截取,就得到我们想要的字符串;
1.=========字符串匹配
NSString *phoneNo =@"13143503442";
NSRange range = [phoneNorangeOfString:@"^1[3]\\d{9}$ options:NSRegularExpressionSearch];//返回在phoneNo中字符串的位置
if (range.location != NSNotFound) {
NSLog(@"%@", [phoneNo substringWithRange:range]);
}
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.============正则表达式中符号的解释
代码 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\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})。
**************************反义****************
\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。
使用小括号的时候,还有很多特定用途的语法。下面列出了最常用的一些:
分类 | 代码/语法 | 说明 |
---|---|---|
捕获 | (exp) | 匹配exp,并捕获文本到自动命名的组里 |
(?<name>exp) | 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp) | |
(?:exp) | 匹配exp,不捕获匹配的文本,也不给此分组分配组号 | |
零宽断言 | (?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp后面的位置 | |
(?!exp) | 匹配后面跟的不是exp的位置 | |
(?<!exp) | 匹配前面不是exp的位置 | |
注释 | (?#comment) | 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 |
代码/语法 | 说明 |
---|---|
\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)都需要为谓词定义谓词表达式,而这个表达式必须是一个返回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);
1.***********比较运算符
=、==:判断两个表达式是否相等,在谓词中=和==是相同的意思都是判断,而没有赋值这一说
NSNumber *testNumber = @123;
NSPredicate *predicate = [NSPredicatepredicateWithFormat:@"SELF = 123"];
if ([predicate evaluateWithObject:testNumber]) {//YES
NSLog(@"testString:%@", testNumber);
}
>=,=>:判断左边表达式的值是否大于或等于右边表达式的值
<=,=<:判断右边表达式的值是否小于或等于右边表达式的值
>:判断左边表达式的值是否大于右边表达式的值
<:判断左边表达式的值是否小于右边表达式的值
!=、<>:判断两个表达式是否不相等
BETWEEN:BETWEEN表达式必须满足表达式 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的第2、3个字符为ac时返回YES。
MATCHES:检查某个字符串是否匹配指定的正则表达式。虽然正则表达式的执行效率是最低的,但其功能是最强大的,也是我们最常用的。例如:上面的例子1;
注:字符串比较都是区分大小写和重音符号的。如:café和cafe是不一样的,Cafe和cafe也是不一样的。如果希望字符串比较运算不区分大小写和重音符号,请在这些运算符后使用[c],[d]选项。其中[c]是不区分大小写,[d]是不区分重音符号,其写在字符串比较运算符之后,比如:name LIKE[cd] 'cafe',那么不论name是cafe、Cafe还是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.*******************集合运算符
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(@"%@", [arrayfilteredArrayUsingPredicate:predicate]);
代码的作用是将array中和filterArray中相同的元素去除,输出为:(a,abcd)
array[index]:返回array数组中index索引处的元素
array[FIRST]:返回array数组中第一个元素
array[LAST]:返回array数组中最后一个元素
array[SIZE]:返回array数组中元素的个数
5.*****************直接量
在谓词表达式中可以使用如下直接量
FALSE、NO:代表逻辑假
TRUE、YES:代表逻辑真
NULL、NIL:代表空值
SELF:代表正在被判断的对象自身
"string"或'string':代表字符串
数组:和c中的写法相同,如:{'one','two','three'}。
数值:包括证书、小数和科学计数法表示的形式
十六进制数:0x开头的数字
八进制:0o开头的数字
二进制:0b开头的数字
6.********************保留字
下列单词都是保留字(不论大小写)
AND、OR、IN、NOT、ALL、ANY、SOME、NONE、LIKE、CASEINSENSITIVE、CI、MATCHES、CONTAINS、BEGINSWITH、ENDSWITH、BETWEEN、NULL、NIL、SELF、TRUE、YES、FALSE、NO、FIRST、LAST、SIZE、ANYKEY、SUBQUERY、CAST、TRUEPREDICATE、FALSEPREDICATE
注:虽然大小写都可以,但是更推荐使用大写来表示这些保留字
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中的方法。
通过上面的描述可以看出,使用谓词过滤不可变集合和可变集合的区别是:过滤不可变集合时,会返回符合条件的集合元素组成的新集合;过滤可变集合时,没有返回值,会直接剔除不符合条件的集合元素
@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]"
)