概念
正則表達式是對字符串操作的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個“規則字符串”,這個“規則字符串”用來表達對字符串的一種過濾邏輯。
給定一個正則表達式和另一個字符串,我們可以達到如下的目的:
- 給定的字符串是否符合正則表達式的過濾邏輯(稱作“匹配”);
- 可以通過正則表達式,從字符串中獲取我們想要的特定部分。
正則表達式的特點是:
- 靈活性、邏輯性和功能性非常的強;
- 可以迅速地用極簡單的方式達到字符串的復雜控制。
- 對于剛接觸的人來說,比較晦澀難懂。
正則表達式的應用:
正則表達式是一種用來進行文本匹配的工具,其語法優美簡潔。在開發中,查找、對比以及匹配字符串是家常便飯的業務,通過正則表達式我們將這些業務描述成某些需求規則,來讓我們的代碼更美觀、實用。
使用步驟
1.定義正則表達式規則
2.通過規則,創建正則表達式對象
3.利用正則表達式對象匹配字符串
注意:正則表達式通常縮寫成“regex”
正則表達式常見的語義語法
/**
* 正則表達式簡單說明
* 語法:
. 匹配除換行符以外的任意字符 \\w 匹配字母或數字或下劃線或漢字 \\s 匹配任意的空白符 \\d 匹配數字 \\b 匹配單詞的開始或結束
^ 匹配字符串的開始 $ 匹配字符串的結束
* 重復零次或更多次
+ 重復一次或更多次
? 重復零次或一次 {n} 重復n次 {n,} 重復n次或更多次 {n,m} 重復n到m次 \\W 匹配任意不是字母,數字,下劃線,漢字的字符 \\S 匹配任意不是空白符的字符 \\D 匹配任意非數字的字符 \\B 匹配不是單詞開頭或結束的位置 [^x] 匹配除了x以外的任意字符 [^aeiou]匹配除了aeiou這幾個字母以外的任意字符
*? 重復任意次,但盡可能少重復
+? 重復1次或更多次,但盡可能少重復
?? 重復0次或1次,但盡可能少重復 {n,m}? 重復n到m次,但盡可能少重復 {n,}? 重復n次以上,但盡可能少重復 \\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
捕獲
(exp) 匹配exp,并捕獲文本到自動命名的組里
(?<name>exp) 匹配exp,并捕獲文本到名稱為name的組里,也可以寫成 (?'name'exp)
(?:exp) 匹配exp,不捕獲匹配的文本,也不給此分組分配組號
零寬斷言
(?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
注釋
(?#comment) 這種類型的分組不對正則表達式的處理產生任何影響,用于提供注釋讓人閱讀
* 表達式:\\(?0\\d{2}[) -]?\\d{8} * 這個表達式可以匹配幾種格式的電話號碼,像(010)88886666,或022-22334455,或02912345678等。
* 我們對它進行一些分析吧:
* 首先是一個轉義字符\\(,它能出現0次或1次(?),然后是一個0,后面跟著2個數字(\\d{2}),然后是)或-或空格中的一個,它出現1次或不出現(?),
* 最后是8個數字(\\d{8})
*/
以下為通過一個分類將常用到的一些正則表達是進行歸類
NSString+RegexCategory.h
#import <Foundation/Foundation.h> @interface NSString (RegexCategory) /**
* 手機號碼的有效性:分電信、聯通、移動和小靈通
*/ - (BOOL)isMobileNumberClassification; /**
* 手機號有效性
*/ - (BOOL)isMobileNumber; /**
* 郵箱的有效性
*/ - (BOOL)isEmailAddress; /**
* 簡單的身份證有效性
*
*/ - (BOOL)simpleVerifyIdentityCardNum; /**
* 精確的身份證號碼有效性檢測
*
* @param value 身份證號
*/ + (BOOL)accurateVerifyIDCardNumber:(NSString *)value; /**
* 車牌號的有效性
*/ - (BOOL)isCarNumber; /**
* 銀行卡的有效性
*/ - (BOOL)bankCardluhmCheck; /**
* IP地址有效性
*/ - (BOOL)isIPAddress; /**
* Mac地址有效性
*/ - (BOOL)isMacAddress; /**
* 網址有效性
*/ - (BOOL)isValidUrl; /**
* 純漢字
*/ - (BOOL)isValidChinese; /**
* 郵政編碼
*/ - (BOOL)isValidPostalcode; /**
* 工商稅號
*/ - (BOOL)isValidTaxNo; /**
@brief 是否符合最小長度、最長長度,是否包含中文,首字母是否可以為數字
@param minLenth 賬號最小長度
@param maxLenth 賬號最長長度
@param containChinese 是否包含中文
@param firstCannotBeDigtal 首字母不能為數字
@return 正則驗證成功返回YES, 否則返回NO
*/ - (BOOL)isValidWithMinLenth:(NSInteger)minLenth
maxLenth:(NSInteger)maxLenth
containChinese:(BOOL)containChinese
firstCannotBeDigtal:(BOOL)firstCannotBeDigtal; /**
@brief 是否符合最小長度、最長長度,是否包含中文,數字,字母,其他字符,首字母是否可以為數字
@param minLenth 賬號最小長度
@param maxLenth 賬號最長長度
@param containChinese 是否包含中文
@param containDigtal 包含數字
@param containLetter 包含字母
@param containOtherCharacter 其他字符
@param firstCannotBeDigtal 首字母不能為數字
@return 正則驗證成功返回YES, 否則返回NO
*/ - (BOOL)isValidWithMinLenth:(NSInteger)minLenth
maxLenth:(NSInteger)maxLenth
containChinese:(BOOL)containChinese
containDigtal:(BOOL)containDigtal
containLetter:(BOOL)containLetter
containOtherCharacter:(NSString *)containOtherCharacter
firstCannotBeDigtal:(BOOL)firstCannotBeDigtal; @end
NSString+RegexCategory.m
#import "NSString+RegexCategory.h" @implementation NSString (RegexCategory) #pragma mark - 正則相關 - (BOOL)isValidateByRegex:(NSString *)regex
{ NSPredicate *pre = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex]; return [pre evaluateWithObject:self];
} #pragma mark - //手機號分服務商 - (BOOL)isMobileNumberClassification{ /**
* 手機號碼
* 移動:134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188,1705
* 聯通:130,131,132,152,155,156,185,186,1709
* 電信:133,1349,153,180,189,1700
*/ // NSString * MOBILE = @"^1((3//d|5[0-35-9]|8[025-9])//d|70[059])\\\\d{7}$";//總況 /**
10 * 中國移動:China Mobile
11 * 134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188,1705
12 */ NSString * CM = @"^1(34[0-8]|(3[5-9]|5[017-9]|8[278])\\\\d|705)\\\\d{7}$"; /**
15 * 中國聯通:China Unicom
16 * 130,131,132,152,155,156,185,186,1709
17 */ NSString * CU = @"^1((3[0-2]|5[256]|8[56])\\\\d|709)\\\\d{7}$"; /**
20 * 中國電信:China Telecom
21 * 133,1349,153,180,189,1700
22 */ NSString * CT = @"^1((33|53|8[09])\\\\d|349|700)\\\\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}$"; // NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE]; if (([self isValidateByRegex:CM])
|| ([self isValidateByRegex:CU])
|| ([self isValidateByRegex:CT])
|| ([self isValidateByRegex:PHS]))
{ return YES;
} else { return NO;
}
} //手機號有效性 - (BOOL)isMobileNumber{ /**
* 手機號以13、15、18、170開頭,8個 \\d 數字字符
* 小靈通 區號:010,020,021,022,023,024,025,027,028,029 還有未設置的新區號xxx
*/ NSString *mobileNoRegex = @"^1((3\\\\d|5[0-35-9]|8[025-9])\\\\d|70[059])\\\\d{7}$";//除4以外的所有個位整數,不能使用[^4,\\\\d]匹配,這里是否iOS Bug? NSString *phsRegex =@"^0(10|2[0-57-9]|\\\\d{3})\\\\d{7,8}$"; BOOL ret = [self isValidateByRegex:mobileNoRegex]; BOOL ret1 = [self isValidateByRegex:phsRegex]; return (ret || ret1);
} //郵箱 - (BOOL)isEmailAddress{ NSString *emailRegex = @"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\\\.[A-Za-z]{2,4}"; return [self isValidateByRegex:emailRegex];
} //身份證號 - (BOOL) simpleVerifyIdentityCardNum
{ NSString *regex2 = @"^(\\\\d{14}|\\\\d{17})(\\\\d|[xX])$"; return [self isValidateByRegex:regex2];
} //車牌 - (BOOL)isCarNumber{ //車牌號:湘K-DE829 香港車牌號碼:粵Z-J499港 NSString *carRegex = @"^[\\u4e00-\\u9fff]{1}[a-zA-Z]{1}[-][a-zA-Z_0-9]{4}[a-zA-Z_0-9_\\u4e00-\\u9fff]$";//其中\\u4e00-\\u9fa5表示unicode編碼中漢字已編碼部分,\\u9fa5-\\u9fff是保留部分,將來可能會添加 return [self isValidateByRegex:carRegex];
}
- (BOOL)isMacAddress{ NSString * macAddRegex = @"([A-Fa-f\\\\d]{2}:){5}[A-Fa-f\\\\d]{2}"; return [self isValidateByRegex:macAddRegex];
}
- (BOOL)isValidUrl
{ NSString *regex = @"^((http)|(https))+:[^\\\\s]+\\\\.[^\\\\s]*$"; return [self isValidateByRegex:regex];
}
- (BOOL)isValidChinese;
{ NSString *chineseRegex = @"^[\\u4e00-\\u9fa5]+$"; return [self isValidateByRegex:chineseRegex];
}
- (BOOL)isValidPostalcode { NSString *postalRegex = @"^[0-8]\\\\d{5}(?!\\\\d)$"; return [self isValidateByRegex:postalRegex];
}
- (BOOL)isValidTaxNo
{ NSString *taxNoRegex = @"[0-9]\\\\d{13}([0-9]|X)$"; return [self isValidateByRegex:taxNoRegex];
}
- (BOOL)isValidWithMinLenth:(NSInteger)minLenth
maxLenth:(NSInteger)maxLenth
containChinese:(BOOL)containChinese
firstCannotBeDigtal:(BOOL)firstCannotBeDigtal;
{ // [\\u4e00-\\u9fa5A-Za-z0-9_]{4,20} NSString *hanzi = containChinese ? @"\\u4e00-\\u9fa5" : @""; NSString *first = firstCannotBeDigtal ? @"^[a-zA-Z_]" : @""; NSString *regex = [NSString stringWithFormat:@"%@[%@A-Za-z0-9_]{%d,%d}", first, hanzi, (int)(minLenth-1), (int)(maxLenth-1)]; return [self isValidateByRegex:regex];
}
- (BOOL)isValidWithMinLenth:(NSInteger)minLenth
maxLenth:(NSInteger)maxLenth
containChinese:(BOOL)containChinese
containDigtal:(BOOL)containDigtal
containLetter:(BOOL)containLetter
containOtherCharacter:(NSString *)containOtherCharacter
firstCannotBeDigtal:(BOOL)firstCannotBeDigtal;
{ NSString *hanzi = containChinese ? @"\\u4e00-\\u9fa5" : @""; NSString *first = firstCannotBeDigtal ? @"^[a-zA-Z_]" : @""; NSString *lengthRegex = [NSString stringWithFormat:@"(?=^.{%@,%@}$)", @(minLenth), @(maxLenth)]; NSString *digtalRegex = containDigtal ? @"(?=(.*\\\\d.*){1})" : @""; NSString *letterRegex = containLetter ? @"(?=(.*[a-zA-Z].*){1})" : @""; NSString *characterRegex = [NSString stringWithFormat:@"(?:%@[%@A-Za-z0-9%@]+)", first, hanzi, containOtherCharacter ? containOtherCharacter : @""]; NSString *regex = [NSString stringWithFormat:@"%@%@%@%@", lengthRegex, digtalRegex, letterRegex, characterRegex]; return [self isValidateByRegex:regex];
} #pragma mark - 算法相關 //精確的身份證號碼有效性檢測 + (BOOL)accurateVerifyIDCardNumber:(NSString *)value {
value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; int length =0; if (!value) { return NO;
}else {
length = (int)value.length; if (length !=15 && length !=18) { return NO;
}
} // 省份代碼 NSArray *areasArray =@[@"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:2]; BOOL areaFlag =NO; for (NSString *areaCode in areasArray) { if ([areaCode isEqualToString:valueStart2]) {
areaFlag =YES; break;
}
} if (!areaFlag) { return false;
} NSRegularExpression *regularExpression; NSUInteger numberofMatch; int year =0; switch (length) { case 15:
year = [value substringWithRange:NSMakeRange(6,2)].intValue +1900; if (year %4 ==0 || (year %100 ==0 && year %4 ==0)) {
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(0, value.length)]; if(numberofMatch >0) { return YES;
}else { return NO;
} case 18:
year = [value substringWithRange:NSMakeRange(6,4)].intValue; if (year %4 ==0 || (year %100 ==0 && year %4 ==0)) {
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(0, value.length)]; if(numberofMatch >0) { int S = ([value substringWithRange:NSMakeRange(0,1)].intValue + [value substringWithRange:NSMakeRange(10,1)].intValue) *7 + ([value substringWithRange:NSMakeRange(1,1)].intValue + [value substringWithRange:NSMakeRange(11,1)].intValue) *9 + ([value substringWithRange:NSMakeRange(2,1)].intValue + [value substringWithRange:NSMakeRange(12,1)].intValue) *10 + ([value substringWithRange:NSMakeRange(3,1)].intValue + [value substringWithRange:NSMakeRange(13,1)].intValue) *5 + ([value substringWithRange:NSMakeRange(4,1)].intValue + [value substringWithRange:NSMakeRange(14,1)].intValue) *8 + ([value substringWithRange:NSMakeRange(5,1)].intValue + [value substringWithRange:NSMakeRange(15,1)].intValue) *4 + ([value substringWithRange:NSMakeRange(6,1)].intValue + [value substringWithRange:NSMakeRange(16,1)].intValue) *2 + [value substringWithRange:NSMakeRange(7,1)].intValue *1 + [value substringWithRange:NSMakeRange(8,1)].intValue *6 + [value substringWithRange:NSMakeRange(9,1)].intValue *3; int Y = S %11; NSString *M =@"F"; NSString *JYM =@"10X98765432";
M = [JYM substringWithRange:NSMakeRange(Y,1)];// 判斷校驗位 if ([M isEqualToString:[value substringWithRange:NSMakeRange(17,1)]]) { return YES;// 檢測ID的校驗位 }else { return NO;
}
}else { return NO;
} default: return NO;
}
} /** 銀行卡號有效性問題Luhn算法
* 現行 16 位銀聯卡現行卡號開頭 6 位是 622126~622925 之間的,7 到 15 位是銀行自定義的,
* 可能是發卡分行,發卡網點,發卡序號,第 16 位是校驗碼。
* 16 位卡號校驗位采用 Luhm 校驗方法計算:
* 1,將未帶校驗位的 15 位卡號從右依次編號 1 到 15,位于奇數位號上的數字乘以 2
* 2,將奇位乘積的個十位全部相加,再加上所有偶數位上的數字
* 3,將加法和加上校驗位能被 10 整除。
*/ - (BOOL)bankCardluhmCheck{ NSString * lastNum = [[self substringFromIndex:(self.length-1)] copy];//取出最后一位 NSString * forwardNum = [[self substringToIndex:(self.length -1)] copy];//前15或18位 NSMutableArray * forwardArr = [[NSMutableArray alloc] initWithCapacity:0]; for (int i=0; i<forwardNum.length; i++) { NSString * subStr = [forwardNum substringWithRange:NSMakeRange(i, 1)];
[forwardArr addObject:subStr];
} NSMutableArray * forwardDescArr = [[NSMutableArray alloc] initWithCapacity:0]; for (int i = (int)(forwardArr.count-1); i> -1; i--) {//前15位或者前18位倒序存進數組 [forwardDescArr addObject:forwardArr[i]];
} NSMutableArray * arrOddNum = [[NSMutableArray alloc] initWithCapacity:0];//奇數位*2的積 < 9 NSMutableArray * arrOddNum2 = [[NSMutableArray alloc] initWithCapacity:0];//奇數位*2的積 > 9 NSMutableArray * arrEvenNum = [[NSMutableArray alloc] initWithCapacity:0];//偶數位數組 for (int i=0; i< forwardDescArr.count; i++) { NSInteger num = [forwardDescArr[i] intValue]; if (i%2) {//偶數位 [arrEvenNum addObject:[NSNumber numberWithInteger:num]];
}else{//奇數位 if (num * 2 < 9) {
[arrOddNum addObject:[NSNumber numberWithInteger:num * 2]];
}else{ NSInteger decadeNum = (num * 2) / 10; NSInteger unitNum = (num * 2) % 10;
[arrOddNum2 addObject:[NSNumber numberWithInteger:unitNum]];
[arrOddNum2 addObject:[NSNumber numberWithInteger:decadeNum]];
}
}
}
__block NSInteger sumOddNumTotal = 0;
[arrOddNum enumerateObjectsUsingBlock:^(NSNumber * obj, NSUInteger idx, BOOL *stop) {
sumOddNumTotal += [obj integerValue];
}];
__block NSInteger sumOddNum2Total = 0;
[arrOddNum2 enumerateObjectsUsingBlock:^(NSNumber * obj, NSUInteger idx, BOOL *stop) {
sumOddNum2Total += [obj integerValue];
}];
__block NSInteger sumEvenNumTotal =0 ;
[arrEvenNum enumerateObjectsUsingBlock:^(NSNumber * obj, NSUInteger idx, BOOL *stop) {
sumEvenNumTotal += [obj integerValue];
}]; NSInteger lastNumber = [lastNum integerValue]; NSInteger luhmTotal = lastNumber + sumEvenNumTotal + sumOddNum2Total + sumOddNumTotal; return (luhmTotal%10 ==0)?YES:NO;
}
- (BOOL)isIPAddress{ NSString *regex = [NSString stringWithFormat:@"^(\\\\d{1,3})\\\\.(\\\\d{1,3})\\\\.(\\\\d{1,3})\\\\.(\\\\d{1,3})$"]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex]; BOOL rc = [pre evaluateWithObject:self]; if (rc) { NSArray *componds = [self componentsSeparatedByString:@","]; BOOL v = YES; for (NSString *s in componds) { if (s.integerValue > 255) {
v = NO; break;
}
} return v;
} return NO;
} @end
掃碼二維碼 獲取免費視頻學習資料
- 本文固定鏈接: http://www.wangchenghua.com/post/4708/
- 轉載請注明:轉載必須在正文中標注并保留原文鏈接
- 掃碼: 掃上方二維碼獲取免費視頻資料
查 看2022高級編程視頻教程免費獲取