iOS之正则表达式的使用和谓词(NSPredicate)的使用
iOS之正则表达式的使用和谓词(NSPredicate)的使用,正则表达式匹配返回的是一个范围,用这个范围去原来的字符串截取,就得到我们想要的字符串;
1.=========字符串匹配
NSString *phoneNo = @"13143503442";
NSRange range = [phoneNo rangeOfString:@"^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 = [regex firstMatchInString:url
options:0
range:NSMakeRange(0, [url length])];
if (match) {
// 截获特定的字符串
NSString *result = [url substringWithRange:match.range];
NSLog(@"%@",result);
}
} else { // 如果有错误,则把错误打印出来
NSLog(@"error - %@", error);
}
// 这个例子是从字符串里检索出以“@”开头“.”结尾的区间字符串,最后检索出来的字符串结尾包括“.”,因此此例子最终输出结果为“qq.”
3.==============//NSRegularExpression类之抓取多个结果
// 当一个字符串有多个符合特定规则的字符,我们可以分别获取到符合特定规则的字符:
NSString *regex = @"\\-\\d*\\.";
NSString *str = @"-34023242.-34203020.";
NSError *error;
NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:regex
options:NSRegularExpressionCaseInsensitive
error:&error];
// 对str字符串进行匹配----把匹配到的字符串全部放入数组,数组中的对象是NSTextCheckingResult
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);
}
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})。
**************************反义****************
\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)。
你也可以自己指定子表达式的组名。要指定一个子表达式的组名,请使用这样的语法:(?
使用小括号的时候,还有很多特定用途的语法。下面列出了最常用的一些:
分类 | 代码/语法 | 说明 |
---|---|---|
捕获 | (exp) | 匹配exp,并捕获文本到自动命名的组里 |
(? |
匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp) | |
(?:exp) | 匹配exp,不捕获匹配的文本,也不给此分组分配组号 | |
零宽断言 | (?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp后面的位置 | |
(?!exp) | 匹配后面跟的不是exp的位置 | |
(? | 匹配前面不是exp的位置 | |
注释 | (?#comment) | 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 |
==============谓词(NSPredicate)==================
只要我们使用谓词(NSPredicate)都需要为谓词定义谓词表达式,而这个表达式必须是一个返回BOOL的值。
谓词表达式由表达式、运算符和值构成。
1.===============evaluateWithObject:是否有匹配的,返回BOOL
NSString*regex =@"^[0-9]*$";//正则匹配小数
NSPredicate*pred = [NSPredicatepredicateWithFormat:@"SELF MATCHES %@", regex];
BOOLisMatch = [predevaluateWithObject:@"99999"];//是否有匹配pre的,有返回YES,没有匹配返回NO;
NSLog(@"--result---%d",isMatch);
2.==========
1.***********比较运算符
=、==:判断两个表达式是否相等,在谓词中=和==是相同的意思都是判断,而没有赋值这一说
NSNumber *testNumber = @123;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"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 = [testArray filteredArrayUsingPredicate: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。
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(@"%@", [array filteredArrayUsingPredicate: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
注:虽然大小写都可以,但是更推荐使用大写来表示这些保留字
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 = [NSPredicate predicateWithFormat:@"%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 = [NSPredicate predicateWithFormat:@"%K > $VALUE", @"age"];
// 指定$SUBSTR的值为 25 这里注释中的$SUBSTR改为$VALUE
NSPredicate *pred1 = [predTemp predicateWithSubstitutionVariables:@{@"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 = [predTemp predicateWithSubstitutionVariables:@{@"VALUE" : @32}];
NSArray *newArray2 = [array filteredArrayUsingPredicate:pred2];
NSLog(@"newArray2:%@", newArray2);
输出为newArray2:(
"[name = Johnson, age = 35, sex = 0]"
)
推荐阅读
-
解析iOS应用的UI开发中懒加载和xib的简单使用方法
-
IOS开发(76)之 NSNotification的使用
-
iOS中使用schema协议调用APP和使用iframe打开APP的例子分析
-
Python爬虫之cookie的获取、保存和使用【新手必学】
-
linux shell之pushd、popd和dirs的使用讲解
-
JS中使用正则表达式g模式和非g模式的区别
-
在iOS开发的Quartz2D使用中实现图片剪切和截屏功能
-
iOS开发中使用Quartz2D绘制上下文栈和矩阵的方法
-
IOS开发入门之storyboard的使用
-
webpack实践之DLLPlugin 和 DLLReferencePlugin的使用教程