正则定义
iOS开发经常需要验证某一事物是否正确,而我们为了验证其正确性就会用到正则表达式(regular expression)其定义是一个描述字符模式的对象。也是一种规则,我们通过这种规则来进行字符串的检索、判断、替换等工作。以下是我们开发时遇到的验证需求,特以此文做笔记。若有错误请告知!
1、手机号验证:
/**
* 判断手机号是否正确
*/
+ (BOOL)valiMobile:(NSString *)mobile{
mobile = [mobile stringByReplacingOccurrencesOfString:@" " withString:@""];
if (mobile.length != 11)
{
return NO;
}else{
NSString * PHONE_NUM = @"^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$";
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", PHONE_NUM];
BOOL isMatch = [pred evaluateWithObject:mobile];
if (isMatch) {
return YES;
}else{
return NO;
}
}
}
注释:
^1匹配输入字符串开始的位置是;
第二位和第三位判断:([358][0-9]|4[579]|66|7[0135678]|9[89]) 。其中 [358][0-9]表示匹配第二位为或者或者第三位为任意数字;4[579]表示第二位为第三位为或者或者;66表示第二位为第三位为。以此类推应当明白7[0135678]和9[89]。
[0-9]{8}$表示匹配8次0到9的数字,即后8位须为数字。
若有新号段可根据注释说明添加判断
2、大陆地区固话验证:
/**
* 大陆地区固话
* 号码:七位或八位
*/
+ (BOOL)isFixedTelephone:(NSString *)phoneNum {
//去除"-"、"()"、"()"按格式样式去除
phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@"-" withString:@""];
phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@"(" withString:@""];
phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@")" withString:@""];
phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@"(" withString:@""];
phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@")" withString:@""];
NSString * FT = @"^0(10|2[0-5789]|\\d{3})\\d{7,8}$";
NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", FT];
return [regextestcm evaluateWithObject:phoneNum];
}
注释:
^匹配输入字符串开始的位置
\d匹配一个数字字符,等价于[0-9]。
{n,m}至少匹配n次,最多匹配m次,尽可能多的匹配。n和m均为非负整数,且n<=m。
$匹配输入字符串结尾的位置
3、身份证号验证:
/**
* 身份证号段正则表达式
*/
+ (BOOL)judgeIdentityStringValid:(NSString *)identityString {
if (identityString.length != 18) return NO;
// 正则表达式判断基本 身份证号是否满足格式
NSString *regex2 = @"^(^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$)|(^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[Xx])$)$";
NSPredicate *identityStringPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex2];
//如果通过该验证,说明身份证格式正确,但准确性还需计算
if(![identityStringPredicate evaluateWithObject:identityString]) return NO;
//** 开始进行校验 *//
//将前17位加权因子保存在数组里
NSArray *idCardWiArray = @[@"7", @"9", @"10", @"5", @"8", @"4", @"2", @"1", @"6", @"3", @"7", @"9", @"10", @"5", @"8", @"4", @"2"];
//这是除以11后,可能产生的11位余数、验证码,也保存成数组
NSArray *idCardYArray = @[@"1", @"0", @"10", @"9", @"8", @"7", @"6", @"5", @"4", @"3", @"2"];
//用来保存前17位各自乖以加权因子后的总和
NSInteger idCardWiSum = 0;
for(int i = 0;i < 17;i++) {
NSInteger subStrIndex = [[identityString substringWithRange:NSMakeRange(i, 1)] integerValue];
NSInteger idCardWiIndex = [[idCardWiArray objectAtIndex:i] integerValue];
idCardWiSum += subStrIndex * idCardWiIndex;
}
//计算出校验码所在数组的位置
NSInteger idCardMod=idCardWiSum%11;
//得到最后一位身份证号码
NSString *idCardLast= [identityString substringWithRange:NSMakeRange(17, 1)];
//如果等于2,则说明校验码是10,身份证号码最后一位应该是X
if(idCardMod==2) {
if(![idCardLast isEqualToString:@"X"]||[idCardLast isEqualToString:@"x"]) {
return NO;
}
}else{
//用计算出的验证码与最后一位身份证号码匹配,如果一致,说明通过,否则是无效的身份证号码
if(![idCardLast isEqualToString: [idCardYArray objectAtIndex:idCardMod]]) {
return NO;
}
}
return YES;
}
4、银行卡号有效性问题Luhn算法:
现行 16 位银联卡现行卡号开头 6 位是 622126~622925 之间的,7 到 15 位是银行自定义的,以下为判断点:
- 可能是发卡分行,发卡网点,发卡序号,第 16 位是校验码。
- 16 位卡号校验位采用 Luhm 校验方法计算:
- 1.将未带校验位的 15 位卡号从右依次编号 1 到 15,位于奇数位号上的数字乘以 2
- 2.将奇位乘积的个十位全部相加,再加上所有偶数位上的数字
- 3.将加法和加上校验位能被 10 整除。
/**
*银行卡号有效性问题Luhn算法
*/
+ (BOOL)isBankCard:(NSString *)cardNum {
if (cardNum.length == 0) {
return NO;
}
NSString * lastNum = [[cardNum substringFromIndex:(cardNum.length - 1)] copy];//取出最后一位
NSString * forwardNum = [[cardNum substringToIndex:(cardNum.length -1)]copy];//前15或18位
NSMutableArray * forwardArr = [[NSMutableArray alloc] initWithCapacity:0];
for (int i=0; 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;
}
该判断亲测满足大部分银行卡验证,如有不全,请自行添加判断。
5 、车牌号码验证
/**
* 车牌号码正则表达式
*/
+(BOOL)checkCarID:(NSString *)carID {
if (carID.length==7) {
//普通汽车,7位字符,不包含I和O,避免与数字1和0混淆
NSString *carRegex = @"^[\u4e00-\u9fa5]{1}[a-hj-np-zA-HJ-NP-Z]{1}[a-hj-np-zA-HJ-NP-Z0-9]{4}[a-hj-np-zA-HJ-NP-Z0-9\u4e00-\u9fa5]$";
NSPredicate *carTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",carRegex];
return [carTest evaluateWithObject:carID];
}else if(carID.length==8){
//新能源车,8位字符,第一位:省份简称(1位汉字),第二位:发牌机关代号(1位字母);
//小型车,第三位:只能用字母D或字母F,第四位:字母或者数字,后四位:必须使用数字;([DF][A-HJ-NP-Z0-9][0-9]{4})
//大型车3-7位:必须使用数字,后一位:只能用字母D或字母F。([0-9]{5}[DF])
NSString *carRegex = @"^[\u4e00-\u9fa5]{1}[a-hj-np-zA-HJ-NP-Z]{1}([0-9]{5}[d|f|D|F]|[d|f|D|F][a-hj-np-zA-HJ-NP-Z0-9][0-9]{4})$";
NSPredicate *carTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",carRegex];
return [carTest evaluateWithObject:carID];
}
return NO;
}
6 、密码验证(6-18位数字和字母组合)
/**
* ^ 匹配一行的开头位置
* (?![0-9]+$) 预测该位置后面不全是数字
* (?![a-zA-Z]+$) 预测该位置后面不全是字母
* [0-9A-Za-z] {6,18} 由6-18位数字或这字母组成
* $ 匹配行结尾位置
*/
+(BOOL)checkPassword:(NSString *) password {
NSString*pattern =@"^(?![0-9]+$)(?![a-zA-Z]+$)[a-zA-Z0-9]{6,18}";
NSPredicate*pred = [NSPredicatepredicateWithFormat:@"SELF MATCHES %@",pattern];
BOOL isMatch = [predevaluateWithObject:password];
return isMatch;
}
注释:
?!表示正向否定预查( Negative look-ahead assertion),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配。
7、邮箱验证
/**
判断邮箱格式是否正确的代码:
@param email 验证的邮箱
@return YES:正确 NO:错误
*/
+ (BOOL)isValidateEmail:(NSString *)email {
NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES%@",emailRegex];
return [emailTest evaluateWithObject:email];
}
注释:
[A-Za-z0-9]匹配字母数字
8、检验是否含有特殊字符
/**
检验是否含有特殊字符:
@param character 验证的字符串
@return YES:是 NO:无
*/
+ (BOOL)isCharacter:(NSString *)character {
NSString *CHARACTER = @"[^%&',;=?$\x22]+";
NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CHARACTER];
return [regextestmobile evaluateWithObject:character];
}
9、判断手机版本型号
+ (NSString*)iphoneType {
//需要导入头文件:#import
struct utsname systemInfo;
uname(&systemInfo);
NSString*platform = [NSString stringWithCString: systemInfo.machine encoding:NSASCIIStringEncoding];
if([platform isEqualToString:@"iPhone1,1"]) return@"iPhone 2G";
if([platform isEqualToString:@"iPhone1,2"]) return@"iPhone 3G";
if([platform isEqualToString:@"iPhone2,1"]) return@"iPhone 3GS";
if([platform isEqualToString:@"iPhone3,1"]) return@"iPhone 4";
if([platform isEqualToString:@"iPhone3,2"]) return@"iPhone 4";
if([platform isEqualToString:@"iPhone3,3"]) return@"iPhone 4";
if([platform isEqualToString:@"iPhone4,1"]) return@"iPhone 4S";
if([platform isEqualToString:@"iPhone5,1"]) return@"iPhone 5";
if([platform isEqualToString:@"iPhone5,2"]) return@"iPhone 5";
if([platform isEqualToString:@"iPhone5,3"]) return@"iPhone 5c";
if([platform isEqualToString:@"iPhone5,4"]) return@"iPhone 5c";
if([platform isEqualToString:@"iPhone6,1"]) return@"iPhone 5s";
if([platform isEqualToString:@"iPhone6,2"]) return@"iPhone 5s";
if([platform isEqualToString:@"iPhone7,1"]) return@"iPhone 6 Plus";
if([platform isEqualToString:@"iPhone7,2"]) return@"iPhone 6";
if([platform isEqualToString:@"iPhone8,1"]) return@"iPhone 6s";
if([platform isEqualToString:@"iPhone8,2"]) return@"iPhone 6s Plus";
if([platform isEqualToString:@"iPhone8,4"]) return@"iPhone SE";
if([platform isEqualToString:@"iPhone9,1"]) return@"iPhone 7";
if([platform isEqualToString:@"iPhone9,2"]) return@"iPhone 7 Plus";
if([platform isEqualToString:@"iPhone10,1"]) return@"iPhone 8";
if([platform isEqualToString:@"iPhone10,4"]) return@"iPhone 8";
if([platform isEqualToString:@"iPhone10,2"]) return@"iPhone 8 Plus";
if([platform isEqualToString:@"iPhone10,5"]) return@"iPhone 8 Plus";
if([platform isEqualToString:@"iPhone10,3"]) return@"iPhone X";
if([platform isEqualToString:@"iPhone10,6"]) return@"iPhone X";
if([platform isEqualToString:@"iPod1,1"]) return@"iPod Touch 1G";
if([platform isEqualToString:@"iPod2,1"]) return@"iPod Touch 2G";
if([platform isEqualToString:@"iPod3,1"]) return@"iPod Touch 3G";
if([platform isEqualToString:@"iPod4,1"]) return@"iPod Touch 4G";
if([platform isEqualToString:@"iPod5,1"]) return@"iPod Touch 5G";
if([platform isEqualToString:@"iPad1,1"]) return@"iPad 1G";
if([platform isEqualToString:@"iPad2,1"]) return@"iPad 2";
if([platform isEqualToString:@"iPad2,2"]) return@"iPad 2";
if([platform isEqualToString:@"iPad2,3"]) return@"iPad 2";
if([platform isEqualToString:@"iPad2,4"]) return@"iPad 2";
if([platform isEqualToString:@"iPad2,5"]) return@"iPad Mini 1G";
if([platform isEqualToString:@"iPad2,6"]) return@"iPad Mini 1G";
if([platform isEqualToString:@"iPad2,7"]) return@"iPad Mini 1G";
if([platform isEqualToString:@"iPad3,1"]) return@"iPad 3";
if([platform isEqualToString:@"iPad3,2"]) return@"iPad 3";
if([platform isEqualToString:@"iPad3,3"]) return@"iPad 3";
if([platform isEqualToString:@"iPad3,4"]) return@"iPad 4";
if([platform isEqualToString:@"iPad3,5"]) return@"iPad 4";
if([platform isEqualToString:@"iPad3,6"]) return@"iPad 4";
if([platform isEqualToString:@"iPad4,1"]) return@"iPad Air";
if([platform isEqualToString:@"iPad4,2"]) return@"iPad Air";
if([platform isEqualToString:@"iPad4,3"]) return@"iPad Air";
if([platform isEqualToString:@"iPad4,4"]) return@"iPad Mini 2G";
if([platform isEqualToString:@"iPad4,5"]) return@"iPad Mini 2G";
if([platform isEqualToString:@"iPad4,6"]) return@"iPad Mini 2G";
if([platform isEqualToString:@"iPad4,7"]) return@"iPad Mini 3";
if([platform isEqualToString:@"iPad4,8"]) return@"iPad Mini 3";
if([platform isEqualToString:@"iPad4,9"]) return@"iPad Mini 3";
if([platform isEqualToString:@"iPad5,1"]) return@"iPad Mini 4";
if([platform isEqualToString:@"iPad5,2"]) return@"iPad Mini 4";
if([platform isEqualToString:@"iPad5,3"]) return@"iPad Air 2";
if([platform isEqualToString:@"iPad5,4"]) return@"iPad Air 2";
if([platform isEqualToString:@"iPad6,3"]) return@"iPad Pro 9.7";
if([platform isEqualToString:@"iPad6,4"]) return@"iPad Pro 9.7";
if([platform isEqualToString:@"iPad6,7"]) return@"iPad Pro 12.9";
if([platform isEqualToString:@"iPad6,8"]) return@"iPad Pro 12.9";
if([platform isEqualToString:@"i386"]) return@"iPhone Simulator";
if([platform isEqualToString:@"x86_64"]) return@"iPhone Simulator";
return platform;
}