欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-04-12 21:13:30
iOS之正则表达式的使用和谓词(NSPredicate)的使用,正则表达式匹配返回的是一个范围,用这个范围去原来的字符串截取,就得到我们想要的字符串; 1.=========字符...

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.============正则表达式中符号的解释

表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)。

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

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

表4.常用分组语法
分类 代码/语法 说明
捕获 (exp) 匹配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]"

)