在iOS開發過程中,我們經常會涉及到這樣的功能例如:校驗手機号、身份證号這樣的功能,我們該如何快速有效的實作這樣的功能呢?正規表達式是一種通用的、常用的方式,優秀的正規表達式可以讓你少寫千行代碼。這裡給大家列舉幾種常用的正規表達式。
正規表達式應用執行個體
1. 手機号碼正規表達式驗證
1) 部落客對部分号段做了補充(17、14号段)如有補充 評論即可 我會及時回複
- (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}$";
/**
29 * 其他号段補充:
30 * 号段:170、176、177、178、145、147
31 * 号碼:八位
32 */
NSString *OT = @"^((17[0678])|(14[57]))\\d{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];
NSPredicate *regextestot = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", OT];
if (([regextestmobile evaluateWithObject:mobileNum] == YES)
|| ([regextestcm evaluateWithObject:mobileNum] == YES)
|| ([regextestct evaluateWithObject:mobileNum] == YES)
|| ([regextestcu evaluateWithObject:mobileNum] == YES)
|| ([regextestot evaluateWithObject:mobileNum] == YES))
{
return YES;
}
else
{
return NO;
}
}
2) 這個是秋秋同學提供的
+ (BOOL)validateMobile:(NSString *)mobile{
//手機号以13, 15,17,18開頭,八個 \d 數字字元
NSString *phoneRegex = @"^((13[0-9])|(17[0])|(17[7])|(14[57])|(15[012356789])|(17[678])|(18[0-9]))\\d{8}$"; NSPredicate *phoneTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",phoneRegex];
return [phoneTest evaluateWithObject:mobile];
}
2. 身份證号碼正規表達式驗證
這個校驗是比較全面和詳細的
- (BOOL)validateIDCardNumber:(NSString *)value {
value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSUInteger length =;
if (!value) {
return NO;
}else {
length = value.length;
if (length != && length !=) {
return NO;
}
}
// 省份代碼
NSArray *areasArray [email protected][@"11",@"12", @"13",@"14", @"15",@"21", @"22",@"23", @"31",@"32", @"33",@"34", @"35",@"36", @"37",@"41",@"42",@"43", @"44",@"45", @"46",@"50", @"51",@"52", @"53",@"54", @"61",@"62", @"63",@"64", @"65",@"71", @"81",@"82", @"91"];
NSString *valueStart2 = [value substringToIndex:];
BOOL areaFlag = NO;
for (NSString *areaCode in areasArray) {
if ([areaCode isEqualToString:valueStart2]) {
areaFlag = YES;
break;
}
}
if (!areaFlag) {
return NO;
}
NSRegularExpression *regularExpression;
NSUInteger numberofMatch;
int year = ;
switch (length) {
case :
year = [value substringWithRange:NSMakeRange(,)].intValue +;
if (year % == || (year % == && year % == )) {
regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$" options:NSRegularExpressionCaseInsensitive error:nil];//測試出生日期的合法性
}else {
regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$" options:NSRegularExpressionCaseInsensitive error:nil];//測試出生日期的合法性
}
numberofMatch = [regularExpression numberOfMatchesInString:value options:NSMatchingReportProgress range:NSMakeRange(, value.length)];
if(numberofMatch >) {
return YES;
}else {
return NO;
}
case :
year = [value substringWithRange:NSMakeRange(,)].intValue;
if (year % == || (year % == && year % ==)) {
regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$" options:NSRegularExpressionCaseInsensitive error:nil];//測試出生日期的合法性
}else {
regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$" options:NSRegularExpressionCaseInsensitive error:nil];//測試出生日期的合法性
}
numberofMatch = [regularExpression numberOfMatchesInString:value options:NSMatchingReportProgress range:NSMakeRange(, value.length)];
if(numberofMatch >) {
int S = ([value substringWithRange:NSMakeRange(,)].intValue + [value substringWithRange:NSMakeRange(,)].intValue) * + ([value substringWithRange:NSMakeRange(,)].intValue + [value substringWithRange:NSMakeRange(,)].intValue) * + ([value substringWithRange:NSMakeRange(,)].intValue + [value substringWithRange:NSMakeRange(,)].intValue) * + ([value substringWithRange:NSMakeRange(,)].intValue + [value substringWithRange:NSMakeRange(,)].intValue) * + ([value substringWithRange:NSMakeRange(,)].intValue + [value substringWithRange:NSMakeRange(,)].intValue) * + ([value substringWithRange:NSMakeRange(,)].intValue + [value substringWithRange:NSMakeRange(,)].intValue) * + ([value substringWithRange:NSMakeRange(,)].intValue + [value substringWithRange:NSMakeRange(,)].intValue) * + [value substringWithRange:NSMakeRange(,)].intValue * + [value substringWithRange:NSMakeRange(,)].intValue * + [value substringWithRange:NSMakeRange(,)].intValue *;
int Y = S %;
NSString *M =@"F";
NSString *JYM =@"10X98765432";
M = [JYM substringWithRange:NSMakeRange(Y,)];// 判斷校驗位
if ([M isEqualToString:[value substringWithRange:NSMakeRange(,)]]) {
return YES;// 檢測ID的校驗位
}else {
return NO;
}
}else {
return NO;
}
default:
return NO;
}
}
這兩個正規表達式是比較常用的,其餘的正規表達式在以後的使用過程中涉及到我會予以補充,也歡迎大家補充說明,我會及時修改補充。
3. 銀行卡号判斷(非正規表達式)
luhn算法,銀行卡的命名以luhn算法為标準。
//-----------------2016年10月3日更新-----------------
- (BOOL) checkCardNo:(NSString*) cardNo{//luhn算法
int oddsum = ; //奇數求和
int evensum = ; //偶數求和
int allsum = ;
int cardNoLength = (int)[cardNo length];
int lastNum = [[cardNo substringFromIndex:cardNoLength-] intValue];
cardNo = [cardNo substringToIndex:cardNoLength - ];
for (int i = cardNoLength - ; i>=;i--) {
NSString *tmpString = [cardNo substringWithRange:NSMakeRange(i-, )];
int tmpVal = [tmpString intValue];
if (cardNoLength % == ) {
if((i % ) == ){
tmpVal *= ;
if(tmpVal>=)
tmpVal -= ;
evensum += tmpVal;
}else{
oddsum += tmpVal;
}
}else{
if((i % ) == ){
tmpVal *= ;
if(tmpVal>=)
tmpVal -= ;
evensum += tmpVal;
}else{
oddsum += tmpVal;
}
}
}
allsum = oddsum + evensum;
allsum += lastNum;
if((allsum % ) == )
return YES;
else
return NO;
}
正規表達式基礎文法規則
【基本文法】
①中括号表示滿足其中之一即可,例如[abc],則這個位置可以是a、b、c中任意一個。
②在中括号中,可以通過-連接配接範圍,例如a-z;多個範圍之間并列不需要任何分隔符,例如[a-zA-Z]。
③表示重複次數用{x},例如[a-z]{2}表示連續2次;表示重複次數的範圍可用{x,y}。
④\d表示數字。
⑤正規表達式預設的是貪婪比對,例如[a-z]{2,4},如果出現類似abcde2ab這樣的字元串,abcd滿足最大長度4,是以會作為一個字元串、e是第二個、ab是第三個。
⑥通配符為.(點),.表示除換行符意外的任意字元。
⑦?表示0個或一個前面的字元、+代表至少一個、*代表0個或多個。
例如zo*,*代表o可以是0個或者多個o,也就是說可以是z、zoo。
⑧以什麼開頭用^,以什麼結尾用$。
⑨OC字元串中的特殊字元用\轉義。
例如[ ]是正則中的特殊表達式,[是普通的‘[‘字元,而OC中\有特殊含義,需要對\再轉義,是以用\[表示‘[‘。
⑩表示中文的範圍為 \u4e00-\u9fa5。
?多個比對條件的并列用|。
比對時一定要注意貪婪比對的問題,否則可能會出錯。
大家可以按照自己的需求修改相應的正規表達式
NSRegularExpression的使用
首先建立對象,然後通過比對模式得到NSTextCheckingResult數組,從中取出對象可以拿到比對到的字元的範圍。
下面的代碼示範了從一個字元串中找出main和if的範圍。
NSString *code = @"mainjiaoififsiifnelsetifajomainiskkl";
NSString *pattern1 = @"main|if";
NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern1 options: error:nil];
NSArray *results = [regex matchesInString:code options: range:NSMakeRange(, code.length)];
for (NSTextCheckingResult *result in results) {
NSLog(@"%@",NSStringFromRange(result.range));
}
內建RegexKitLite
利用系統的對象進行比對比較麻煩,下面介紹一個強大的第三方庫RegexKitLite
①首先從github下載下傳RegexKitLite。
②将檔案RegexKitLite.m和.h導入到工程。
③由于該庫比較老,不支援ARC,是以應該為RegexKitLite.m添加編譯标記-fno-objc-arc進行局部ARC禁止。
④添加動态庫libicucore.dylib。
注意③和④都在Build Phases中進行設定,如下圖所示:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX9kkaNlXRU9UNFpHZxFjMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DMyMTN0cTMzEzNwUDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
通過以上幾步就完成了內建,下面介紹該庫的常用方法。
該庫是NSString的分類,是以字元串可以直接調用方法,常用的方法有比對和分割。
①比對:傳入比對模式pattern即可,可以擷取比對到的字元串和範圍。
[str enumerateStringsMatchedByRegex:pattern usingBlock:^(NSInteger captureCount, NSString *const __unsafe_unretained *capturedStrings, const NSRange *capturedRanges, volatile BOOL *const stop) {
NSRange range = *capturedRanges;
NSLog(@"%@ %@",*capturedStrings,NSStringFromRange(range));
}];
②分割:有時候有一種需求,需要擷取到所有比對到的内容之外的字串,也就是利用正則内容分割字元串,可以得到比對到的字串以外的字元串和範圍。
[str enumerateStringsSeparatedByRegex:pattern usingBlock:^(NSInteger captureCount, NSString *const __unsafe_unretained *capturedStrings, const NSRange *capturedRanges, volatile BOOL *const stop) {
NSRange range = *capturedRanges;
NSLog(@"%@ %@",*capturedStrings,NSStringFromRange(range));
}];