在开发中,我们需要验证用户的输入信息,多半采用正则验证,下面就是身份证证号的几种常用的正则表达式:

var  reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;

var reg= /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/;

var  reg = /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$/;

但是这些并不能管用,是不是很气人?

这是为什么呢?

下面我们看一下身份证的规则

身份证查询系统说明:

输入准确的18位身份证号码即可查询身份证号码归属地,年龄,性别,通过身份证号码查询姓名。

输入不合法格式的身份证号码会提示身份证号码错误,本身份证号码查询系统也可作为身份证号码验证。

身份证号码和姓名格式科普:前1-6位为行政区划代码即归属地,第7-14位为出生年月日,第15-17位为顺序代码,在同一个地区出生同一个出生的人通过顺序号码区分,第17位奇数表示男性,偶数表示女性,第18位为校验码,用于校验身份证号码是否合法

很显然我们正则验证出错的原因就是第18位,用于身份证号是否合法验证的校验

这是为什么呢?是不是很诡异?按照道理讲,不应该不符合就是false?但是返回的都是true;

因为是这样的,我们使用的正则表达式 reg.test(''),当我们使用test其实就是通过我们写的正则表达式去动态匹配我们输入的字符串是否符合我们表达式的要求,如果符合就会返回Boolean值

这就是为什么我们身份证验证会出错,因为我们正则只是匹配了形式,并没有按照身份证的规则去动态验证,没有权重

那么正确的验证如下

 /**
* @params idCard string
* @outParams res
* status : boolean
* msg : string
*
*/
function checkIdcard(idCard) {
idCard = idCard.toString();
var city = {
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: "国外 "
};
var tip = "";
var pass = true; if (
!idCard ||
!/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i.test(
idCard
)
) {
tip = "身份证号格式错误";
pass = false;
} else if (!city[idCard.substr(0, 2)]) {
tip = "地址编码错误";
pass = false;
} else {
//18位身份证需要验证最后一位校验位
if (idCard.length == 18) {
idCard = idCard.split("");
//∑(ai×Wi)(mod 11)
//加权因子
var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
//校验位
var parity = [1, 0, "X", 9, 8, 7, 6, 5, 4, 3, 2];
var sum = 0;
var ai = 0;
var wi = 0;
for (var i = 0; i < 17; i++) {
ai = idCard[i];
wi = factor[i];
sum += ai * wi;
}
var last = parity[sum % 11];
if (parity[sum % 11] != idCard[17]) {
tip = "校验位错误";
pass = false;
}
}
}
var obj = {
status: pass,
msg: tip
};
if (!pass) {
return obj;
} return obj;
}

写法注意事项:省区编码,我们可以写成数组的形式,但是需要去循环操作,会比较消耗性能:如果是数组,新手是这么写的

function checkIdcard(idCard) {
idCard = idCard.toString();
var city = [
11,
12,
13,
14,
15,
21,
22,
23,
31,
33,
34,
35,
36,
37,
41,
42,
43,
44,
45,
46,
50,
51,
52,
54,
61,
62,
63,
64,
65,
71,
81,
91
];
var tip = "";
var pass = true;
var Flag = true;
for(var i=0;i<city.length;i++){
if (city[i] == idCard.substr(0, 2)) Falg= false;
}
if (
!idCard ||
!/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i.test(
idCard
)
) {
tip = "身份证号格式错误";
pass = false;
} else if (!Flag) {
tip = "地址编码错误";
pass = false;
} else {
//18位身份证需要验证最后一位校验位
if (idCard.length == 18) {
idCard = idCard.split("");
//∑(ai×Wi)(mod 11)
//加权因子
var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
//校验位
var parity = [1, 0, "X", 9, 8, 7, 6, 5, 4, 3, 2];
var sum = 0;
var ai = 0;
var wi = 0;
for (var i = 0; i < 17; i++) {
ai = idCard[i];
wi = factor[i];
sum += ai * wi;
}
var last = parity[sum % 11];
if (parity[sum % 11] != idCard[17]) {
tip = "校验位错误";
pass = false;
}
}
}
var obj = {
status: pass,
msg: tip
};
if (!pass) {
return obj;
} return obj;
}

  优化上面的代码

/**
* @params idCard string
* @outParams res
* status : boolean
* msg : string
*
*/
function checkIdcard(idCard) {
idCard = idCard.toString();
var city = [
11,
12,
13,
14,
15,
21,
22,
23,
31,
33,
34,
35,
36,
37,
41,
42,
43,
44,
45,
46,
50,
51,
52,
54,
61,
62,
63,
64,
65,
71,
81,
91
];
var tip = "";
var pass = true; if (
!idCard ||
!/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i.test(
idCard
)
) {
tip = "身份证号格式错误";
pass = false;
} else if (city.indexOf(idCard.substr(0, 2)) < 0) {
tip = "地址编码错误";
pass = false;
} else {
//18位身份证需要验证最后一位校验位
if (idCard.length == 18) {
idCard = idCard.split("");
//∑(ai×Wi)(mod 11)
//加权因子
var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
//校验位
var parity = [1, 0, "X", 9, 8, 7, 6, 5, 4, 3, 2];
var sum = 0;
var ai = 0;
var wi = 0;
for (var i = 0; i < 17; i++) {
ai = idCard[i];
wi = factor[i];
sum += ai * wi;
}
var last = parity[sum % 11];
if (parity[sum % 11] != idCard[17]) {
tip = "校验位错误";
pass = false;
}
}
}
var obj = {
status: pass,
msg: tip
};
if (!pass) {
return obj;
} return obj;
}

注意一下写法,尽量减少循环的操作,推荐使用第一种和第三种用法;如果你是es6用户,那么建议var 修改成 let

最后基于模块的思想,建议搭建可以在实际开发中,把验证的方法统一一个对象去处理,

然后哪里需要哪里引入。

参考博文:https://blog.csdn.net/a632202838/article/details/44827427

在线身份查询:http://sfz.diqibu.com/

正则匹配身份证有bug你知道么?的更多相关文章

  1. js正则匹配身份证号 有坑

    // 不能加g,每次匹配会以lastIndex为起始位去查找 // 若加g,匹配到会用最后一位的index去改变lastIndex,没有匹配到则会把lastIndex重置为0 // 不加g,lastI ...

  2. 详解一个自己原创的正则匹配IP的表达式

    这里给大家详细讲解一下一个匹配IP地址的正则表达式, 有关正则方面的知识,会在详细的讲解中提到. 在讲解之前,我先给大家介绍一下,ip地址的生成规则. IP地址,是由32位数字二进制转为四个十进制的字 ...

  3. jQuery中的一些正则匹配表达式

    jQuery常用正则匹配表达式 落雨 //整数 "^-?[1-9]\\d*$", //正整数 "^[1-9]\\d*$", //负整数 intege2: &qu ...

  4. 常用的JavaScript正则匹配规则代码收藏,很实用

    收集一些常用的JavaScript正则表达式匹配规则,比如匹配电话号码.Email.中文字符.身份证号.邮编.QQ号.过滤空白行.匹配特定数字等.觉得这玩意是很有用的,只不过自己水平菜,老是自己写不出 ...

  5. 正则匹配<img src="xxxxxx" alt="" />标签的相关写法

    1.(<img\ssrc[^>]*>) 2.content.replace(/<img [^>]*src=['"]([^'"]+)[^>]*&g ...

  6. iOS 中的正则匹配(工具类方法)

    正则表达式 正则表达式是对字符串操作的一种逻辑公式, 用事先定义好的一些特定字符.及这些特定字符的组合, 组成一个"规则字符串", 这个"规则字符串"用来表达对 ...

  7. js 空正则匹配任意一个位置

    看一个正则 这里明显,起到匹配作用的是 | 后的,可 | 后什么都没有,原理不知道,也没有搜到文献,只有在 Reg101 上是这样解释的, 所以得出结论: js 中,空正则匹配任意一个位置. 不过,这 ...

  8. 通用且常用的Java正则匹配工具,用以检查邮箱名、电话号码、用户密码、邮政编码等合法性

    一个通用且常用的Java正则匹配工具,用以检查邮箱名.电话号码.用户密码.邮政编码等合法性. import java.util.regex.Matcher; import java.util.rege ...

  9. JS正则表达式一些基本使用、验证、匹配、正则匹配时一个变量

    js验证首位必须是字母 var str = "asfg"; /^[a-zA-Z].*/.test(str);//true是,false否 匹配所有空格 var str=" ...

随机推荐

  1. defer 的常用场景

    将panic的转化为error类型值,并将其作为函数值返回给调用方 package main import "fmt" func divide(a, b int) (res int ...

  2. android开发学习——day5

    活动跳转部分代码显式intent @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(saved ...

  3. IdentityServer4之Clients、Scopes、Claims与Token关联

    IdentityServer4之Clients.Scopes.Claims与Token关联 参考 官方文档:client.identity_resource.api_resource:三类配置项介绍描 ...

  4. SpringSecurity学习之自定义过滤器

    我们系统中的认证场景通常比较复杂,比如说用户被锁定无法登录,限制登录IP等.而SpringSecuriy最基本的是基于用户与密码的形式进行认证,由此可知它的一套验证规范根本无法满足业务需要,因此扩展势 ...

  5. Javac常量池的解读

    interface IA{ public void md(); } public class Test07 implements IA{ final double d = 2.0d; final fl ...

  6. geo-经纬度计算

    经纬度计算, 本质上是球面三角函数的应用, 将数学公式转换为代码的过程, 站在前人的肩膀上, 自己又补充了一点: package com.iwhere.easy.travel.tool; public ...

  7. MVC返回文件

    上一篇 介绍了Action 返回View, 顺便也看到了返回Json的处理, 这一篇并不看文件返回的源码, 此篇是为了应用. 1. Response返回文件 在MVC的项目中, 还是能看到很多同事, ...

  8. 命令行下更好显示 postgresql 的查询结果

    之前在用 mysql 的时候发现,当列数特别多的时候,在 linux 命令行下,显示不太友好, 然后可以通过将 sql 末尾的 “:” 改为 “\G” 来处理,详情看 命令行下更好显示 mysql 查 ...

  9. Java 8 新特性-菜鸟教程 (0) -Java 8 新特性

    Java 8 新特性 Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本. Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 ...

  10. http缓存详解,http缓存推荐方案

    前言 通过本文,你将了解到http缓存机制是怎样的,no-cache到底有没有缓存,地址栏回车,F5,ctrl+F5的区别,以及当下较为推荐的缓存方案等. 自从和前端组的同事一起整了个前端扫盲计划,想 ...