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

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. 使用控制台程序搭建WebApi

    原文参考: ASP.NET Web Api 2.2: Create a Self-Hosted OWIN-Based Web Api from Scratch 新建控制台程序,引入Owin包 PM&g ...

  2. 12 二叉树-链式存储-二叉排序树(BST)

    呜呜 写这个东西花了我2天 居然花了两天!!我还要写AVL呢啊啊啊啊啊啊啊!!!!!! 等下还要跑去上自习 大早上起来脸都没洗现在先赶紧发博客 昨晚写出来了独自在其他人都睡着了的宿舍狂喜乱舞.. 迷之 ...

  3. wangEditor使用简记

    页面 <!--用父容器来控制宽度--> <div style="width:800px"> <!--用当前元素来控制高度--> <text ...

  4. Centos7 开启端口

    CentOS7默认没有使用iptables,所以通过编辑iptables的配置文件来开启80端口是不可以的. CentOS 7 采用了 firewalld 防火墙. 如要查询是否开启80端口: [ro ...

  5. gcc编译时对’xxxx’未定义的引用问题

    gcc编译时对’xxxx’未定义的引用问题 原因 解决办法 gcc 依赖顺序问题 在使用gcc编译的时候有时候会碰到这样的问题,编译为.o(obj) 文件没有问题,但是编译(这一步应该是链接)为可执行 ...

  6. docker-dockerfile使用

    使用 centos基础镜像, 构建dockerfile-ngix 简单说, 就是把需要做的东西写下来, 然后build的时候, 自动运行 一般包含:  基础镜像信息 维护者信息 镜像操作指令 容器启动 ...

  7. U盘安装原版Win7或Win8教程

    具体步骤: 1.先使用大白菜U盘启动制作工具制作完U盘启动(参照制作教程). 2.找到Windows7系统的iso镜像,用UltraISO或者WinRAR打开Win7的iso镜像,然后提取/解压所有文 ...

  8. study design of ADNI

    AD(Alzheimer’s disease):不可逆的神经退化,患病人员会由于脑部问题的恶化而导致心智功能不健全. ADNI:阿尔茨海默氏症神经成像项目 ADNI的总体目标是验证用于阿尔茨海默病临床 ...

  9. js实现响应式瀑布流

    导读:瀑布流,又称瀑布流式布局.是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部.最早采用此布局的网站是Pinterest ...

  10. .Net下SQLite的DBHelp

    怎样获取SqLite请参考初识SqlLite ---.net连接数据库,怎样在SQLite使用Linq请参考在C#中利用Nuget包使用SQLite数据库和Linq to SQLite using S ...