常见数据格式的正则表达式验证

目录

前言

  正则表达式是一种强大的工具,可以在很多场景下对我们需要的内容进行快速匹配过滤。比如,在前端提交表单时,就可以通过编写合理的正则表达式对用户输入进行首次过滤(当然服务端程序在接收到数据后一样要进行严格的数据检查,保证程序正常运行,防止通过postman等工具绕过前端验证进行恶意攻击。)

正则表达式的学习

  网上有很多系统学习正则表达式的资源,掌握基本的语法和相关机制是实现常见数据格式验证的基础。快速了解正则表达式的内容,推荐廖雪峰JavaScript教程中的正则RegExp部分
  需要单独说明的是,以下提到的各种数据格式的验证,都采用JavaScript中的如下写法:

1
2
3
4
var reg = /正则表达式/;
var strToTest = "待测试内容";
reg.test(strToTest); //返回true或者false表明正则验证通过或失败
strToTest.match(reg); //以数组形式返回匹配正确的部分,若没有返回null

验证输入是否为空

表达式

1
var reg = /^$/;

解释

^匹配开始,$匹配结束,上述表达式的意思是匹配的字符串开始结束之间没有内容。test()方法返回true则表示输入内容为空(输入空格等并不为空)。


验证输入是否为英文字母(大小写)+数字

表达式

1
var reg = /^[a-zA-Z0-9]+$/;

解释

分别列出小写a-z,大写A-Z,数字0-9即可。

验证输入是否为英文字母(大小写)+数字+下划线

表达式

1
var reg = /^\w+$/;

解释

正则表达式中\w就表示匹配一个数字或者字母,也包含了下划线。

验证输入是否为汉字

表达式

1
var reg = /^[\u4e00-\u9fa5]{0,}$/;

解释

\u4e00是汉字“一”,\u9fa5是汉字“龥”,该范围包含了汉字的Unicode编码。

验证输入是否为整数

表达式

1
var reg = /^\-?[1-9]\d*$/;

解释

  1. 这个表达式可以用来匹配除0以外的任意正负整数。
  2. 开始是一个负号“-”,用来匹配负数的负号,?表示非贪婪匹配模式(也就是说匹配尽量少的内容,一旦匹配上就不再考虑后面的字符串)。并且?表示匹配其前面的内容0次或者1次,这样就包括了正数和负数都可以。注意这里的-号后面不能接*或者+,必须只能至多有一个。
  3. [1-9]则表示匹配一个1-9的数字,作为整个这个整数的开头。注意这里必须将第一位这样处理,因为不能为0,无法和后面的\d*合并。
  4. \d*则表示后续接的0个或多个数字,和前面的部分共同构成整数。

验证输入是否为正整数

表达式

1
var reg = /^\+?[1-9]\d*$/;

解释

  1. 开始可以有一个正号(最多一个),当然也可以没有。并且由于+在正则表达式中有特殊含义,因此必须转义。
  2. [1-9]则表示匹配一个1-9的数字,作为整个这个整数的开头。注意这里必须将第一位这样处理,因为不能为0,无法和后面的\d*合并。
  3. \d*则表示后续接的0个或多个数字,和前面的部分共同构成整数。

验证输入是否为负整数

表达式

1
var reg = /^\-[1-9]\d*$/;

解释

  1. 一开始必须有一个负号,并且由于-在正则表达式中有特殊含义,因此转义。
  2. [1-9]则表示匹配一个1-9的数字,作为整个这个整数的开头。注意这里必须将第一位这样处理,因为不能为0,无法和后面的\d*合并。
  3. \d*则表示后续接的0个或多个数字,和前面的部分共同构成整数。

验证输入是否为非负整数(正整数 + 0)

表达式

1
var reg = /^((\+?[1-9]\d*)|(0))$/;

解释

  1. 正数前面可能会有正号,\+?限制有0个或者1个正号。
  2. 随后是一位1-9的数字[1-9],再随后是任意多位0-9的数字\d*,排除掉“+02”这样无意义的写法。
  3. 对于0,直接匹配(0)。
  4. 上述情况,居其一,用或|区分,整体上必须还用括号()包起来,否则无法正确过滤”-0”这种情况。

验证输入是否为非正整数(负整数 + 0)

表达式

1
var reg = /^((\-[1-9]\d*)|(0))$/;

解释

  1. 对于0,直接匹配(0)。
  2. 对于小于零的负整数,开头是负号-,随后是一位1-9的数字[1-9],再随后是任意多位0-9的数字\d*
  3. 上述两种情况,居其一,用或|区分,整体上必须还用括号()包起来,否则无法正确过滤”-0”这种情况。

验证输入是否为n位的数字

表达式

1
var reg = /^\d{n}$/; //具体使用时n取某个特定数字

解释

{n}表示\d数字的个数。

验证输入是否为至少n位的数字

表达式

1
var reg = /^\d{n,}$/;

解释

{n,}表示\d数字的个数范围。

验证输入是否为m~n位的数字

表达式

1
var reg = /^\d{m,n}$/;

解释

{n,m}表示\d数字的个数范围。

验证输入是否为浮点数

表达式

1
var reg = /^(\-?\d+)(\.\d+)?$/;

解释

  1. 开始是一个负号“-”,用来匹配负数的负号,?表示非贪婪匹配模式(也就是说匹配尽量少的内容,一旦匹配上就不再考虑后面的字符串)。并且?表示匹配其前面的内容0次或者1次,这样就包括了正数和负数都可以。注意这里的-号后面不能接*或者+,必须只能至多有一个。
  2. 随后\d+表示1位或者多位数字,代表该浮点数的整数部分。
  3. \.转义表示小数点。
  4. \d+表示1位或者多位数字,代表该浮点数的小数部分。

验证输入是否为正浮点数

表达式

1
var reg = /^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$/;

解释

  1. 开始一位1-9的数字[1-9],再随后是任意多位0-9的数字\d*,表示正浮点数整数部分(且是大于等于1的浮点数)。
  2. \.转义表示小数点。
  3. \d*表示0位或者多位数字,代表该浮点数的小数部分。
  4. 再考虑0-1之间的浮点数,\d*[1-9]\d*的写法是为了防止0.000这种情况。

验证输入是否为负浮点数

表达式

1
var reg = /^\-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$/;

解释

  1. 开头匹配负号’-‘
  2. 考虑小于等于-1的浮点数,一位1-9的数字[1-9],再随后是任意多位0-9的数字\d*,表示负浮点数整数部分。
  3. \.转义表示小数点。
  4. \d*表示0位或者多位数字,代表该浮点数的小数部分。
  5. 再考虑-1~0之间的浮点数,0直接匹配0。
  6. \.转义表示小数点。
  7. \d*[1-9]\d*的写法是为了防止0.000这种情况。

验证输入是否为非负浮点数

表达式

1
var reg = /^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$/;

解释

  1. 前半部分[1-9]\d*\.\d*|0\.\d*[1-9]\d*与正浮点数一样,不再赘述。
  2. 0?表示0个或1个‘0’,这是允许的,针对的是“.666”这种写法的浮点数。
  3. 最后一部分直接匹配“0”,也是可以的。

验证输入是否为非正浮点数

表达式

1
var reg = /^(\-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$/;

解释

  1. 前半部分\-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)与负浮点数一样,不再赘述。
  2. 0?表示0个或1个‘0’,这是允许的,针对的是“.666”这种写法的浮点数。
  3. 最后一部分直接匹配“0”,也是可以的。

验证输入是否为有两位小数的正实数

表达式

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

解释

  1. ([1-9]\d*(.[0-9]{2})?)匹配大于等于1的两位小数实数
  2. (0.[1-9][0-9])匹配0.10~0.99的两位小数实数
  3. (0.[0-9][1-9])匹配0.01~0.99(但不含0.10 0.20 0.30 … 0.90这些数)
  4. 2,3中的处理是为了排除0.00这个数(非正)

验证输入是否为有1~3位小数的正数或负数

表达式

1
var reg = /^(\-)?\d+(\.\d{1,2})?$/;

解释

  1. (-)?匹配0或1个负号
  2. \d+表示该数的整数部分
  3. (.\d{1,3})?匹配小数点和1~3位小数

验证输入是否为email地址

表达式

1
var reg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;

解释

  1. \w+表明必须以字母数字下划线开头。
  2. 随后可接任意个([-+.]\w+)的组合。组合的内容是:一个’-‘或’+’或’.’加上至少一个字母数字下划线。
  3. @直接匹配地址符@。
  4. @后面必须接至少一个字母数字下划线。
  5. 随后可接任意个([-.]\w+)的组合。组合的内容是:一个’-‘或’.’加上至少一个字母数字下划线。
  6. 随后单独匹配一个\.,表明@后面至少是二级域名。
  7. 随后仍可接任意个([-.]\w+)的组合。注意必须以字母数字下划线结尾。

验证输入是否为中国邮政编码

表达式

1
var reg = /^\d{6}$/;

解释

邮编为6位数字。另外有些地方关于邮编的正则验证是[1-9]\d{5}(?!\d)。我认为有两个问题:

  1. 邮编第一位可以为零,比如027200:内蒙古自治区 锡林郭勒盟 正蓝旗
  2. 最后加一个零宽负向先行断言(?!\d)是没有必要的,想限制第六位后面没有数字,直接$即可。

验证输入是否为URL

表达式

1
var reg = /^$/;

解释

URL的灵活性很强,因此不好找到一种能包罗万象的匹配方式,上述提供的只能说可以应对大部分,但使用时要注意,如果加上了这个限制反而导致用户本来正确合理的输入无法通过验证进而提交表单,那么不如不用。

验证输入是否为身份证号码

表达式

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

解释

  1. 早期身份证号码为15位,均为数字;后来增加为18位编码,最后一位是校验位,可能出现“10”,对应地采用罗马字母X表示。
  2. 分别验证了15位数字、18位数字、17位数字+字母x/X三种情况。要注意的是每种情况必须都写结束符$,否则只要大于等于15位都会匹配成功。
  3. 以上正则验证只能说是对数字位数和是否有字母做出了限定,但并不能详细校验是否符合规则-比如地区编号,性别等,这些超出了正则的验证范围(或者说正则解决起来反而会变得麻烦),这时候,想进一步验证输入,要采取更详细的办法,详见JavaScript 18位身份证验证及身份证号码规则

验证输入是否为一年的12个月

表达式

1
var reg = /^(0?[1-9]|1[0-2])$/;

解释

  1. 0?这种写法保证了比如9、09都可以被接受,而不是非得两位。
  2. 10,11,12月单独处理。

验证输入是否为一月的31天

表达式

1
var reg = /^(0?[1-9]|(1|2)[0-9]|3[0-1])$/;

解释

0?这种写法保证了比如9、09都可以被接受,而不是非得两位。

验证输入是否为YYYY-MM-DD格式的日期

表达式

1
var reg = /^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$/;

解释

  1. 考虑了平年闰年。

  2. (?:(?!0000)[0-9]{4}匹配年份。
    2.1 ?:表明这是非捕获分组,后面括号匹配到的内容不会被存入内存中,这样是为了提高匹配效率和性能(后面大量出现?:,都是这个作用)。
    2.2 ?!表明这是零宽负向先行断言,表明在此位置后面的不是“0000”才会匹配,结合[0-9]{4}来看,这是为了去掉年份为“0000”的。

  3. 后面分多种情况匹配了月和日:
     3.1 “(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)”
      3.1.1 “?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])”
        3.1.1.1 “?:(?:0[1-9]|1[0-2])”
          匹配01-09月,以及10-12月。
        3.1.1.2 “(?:0[1-9]|1[0-9]|2[0-8])”
          匹配01-09日,10-19日,20-28日。这些是任何一年的任何一个月都会有的日期。
      3.1.2 “(?:0[13-9]|1[0-2])-(?:29|30)”
        3.1.2.1 “(?:0[13-9]|1[0-2])”
          匹配01月、03-09月,以及10-12月。也就是除去02月,考虑到02月只有28/29天。
        3.1.2.2 “(?:29|30)”
          当月份匹配01月、03-09月,以及10-12月时,对应的日就可以有29、30日。
      3.1.3 “(?:0[13578]|1[02])-31)”
        3.1.3.1 “(?:0[13578]|1[02])”
          匹配01,03,05,07,08,10,12月,这些月份会有31号。
        3.1.3.2 “-31”
          匹配31日。
     3.2 “(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29”
      3.2.1 “(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)”
        3.2.1.1 “(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])”
          从3.2开始是匹配一些特殊的年份-闰年。即年份“能被400整除”或者“能被4整除且不能被100整除”的。先考虑“能被4整除且不能被100整除”:前两位0-9皆可。后两位只要不是“00”,就能保证不被100整除,因此只需要考虑后两位被4整除的情况,也就是考虑01-99之中能被4整除的有哪些,即(?:0[48]|[2468][048]|[13579][26])。
        3.2.1.2 “(?:0[48]|[2468][048]|[13579][26])00”
          再考虑“能被400整除”的,后两位肯定是00,考虑前两位。只要前两位能被4整除即可,也即(?:0[48]|[2468][048]|[13579][26])。
      3.2.2 “-02-29”
        处理完年份后,即得到所有的闰年后,月日就是固定的02-29。

验证输入是否为YYYY-MM-DD hh:mm:ss格式的日期

表达式

1
var reg = /^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29) (([0-1][0-9])|(2[0-3]))\:[0-5][0-9]\:[0-5][0-9]$/;

解释

  1. YYYY-MM-DD部分与上面相同,不再赘述。
  2. (([0-1][0-9])|(2[0-3]))整体是一个分组,要加括号,匹配时:00-23
  3. [0-5][0-9],匹配分:00-59
  4. [0-5][0-9],匹配秒:00-59

验证输入是否为hh:mm:ss格式的时间

表达式

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

解释

与上面的hh:mm:ss相同,不再赘述。

验证输入是否为手机号码

表达式

1
var reg = /^1[3|4|5|7|8]\d{9}$/;

解释

  1. 号段分布
    中国移动号段:
    134 135 136 137 138 139 147 150 151 152 157 158 159 178 182 183 184 187 188
    中国联通号段:
    130 131 132 145 155 156 171 175 176 185 186
    中国电信号段:
    133 149 153 173 177 180 181 189
    虚拟运营商:
    170
  2. 第一位匹配1即可。
  3. 第二位从上面的分布看有3,4,5,7,8。
  4. 后面的9位可以是任意9位数字。
  5. 该正则基于以上号段,号段可能会更新,因此相应正则表达式也需要调整。

验证输入是否为中国座机号码

表达式

1
var reg = /^\d{3}-\d{8}|\d{4}-\d{7}$/;

解释

  1. 考虑区号3位,电话号8位的情况,格式示例010-62281100
  2. 考虑区号4位,电话号7位的情况,格式示例0532-1111111
  3. 考虑区号4位,电话号8位的情况,格式示例0571-88856088

验证输入是否为IPV4地址

表达式

1
var reg = /^\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b$/;

解释

  1. \b代表着单词的开头或结尾,也就是单词的分界处。此处使用的意思是IP地址前后要是“分开的”,没有和其他任何内容连在一起
  2. “(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}”
    IPV4格式为“xxx.xxx.xxx.xxx”,这部分匹配前三个,还带上了点号”.”。一共考虑了这几种情况:
     2.1 [01]?[0-9][0-9]?: 可能只有一位,如0.0.0.0;可能两位:如10.3.8.211;可能三位,如121.43.160.59
     2.2 2[0-4][0-9]: 考虑200~249的情况
     2.3 25[0-5]: 考虑250-255的情况

验证输入是否为IPV6地址

表达式

1
var reg = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;

解释

验证输入是否为密码要求的格式

表达式

1
var reg = /^[a-zA-Z]\w{5,19}$/;

解释

密码格式要求不是固定的,上述只是其中一种:以字母开头,只能包含大小写字母、数字、下划线。长度在6~20位。

验证输入密码安全强度

表达式

1
var reg = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{15,20}$/;

解释

1.”.”在正则中表示“元字符”,它可以匹配除”\n”以外的任何字符。
2.”?=pattern”是一个零宽正向先行断言,紧接该位置之后的字符序列能够匹配pattern。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
3.”(?=.\d)(?=.[a-z])(?=.*[A-Z])”这段表示在有任意个除”\n”以外的任何字符的同时,密码中必须包括数字,大小写字母。
4.多长的密码算“高强度”,视需求而定,这里取15位以上为高强度。

匹配首尾空白字符

表达式

1
var reg = /^\s*|\s*$/;

解释

\s匹配任何空白字符,包括空格、制表符、换页符、回车符、换行符等等。等价于 [\f\n\r\t\v]。

匹配中文标点符号

表达式

1
var reg = /^[\u3002|\uff1f|\uff01|\uff0c|\u3001|\uff1b|\uff1a|\u201c|\u201d|\u2018|\u2019|\uff08|\uff09|\u300a|\u300b|\u3008|\u3009|\u3010|\u3011|\u300e|\u300f|\u300c|\u300d|\ufe43|\ufe44|\u3014|\u3015|\u2026|\u2014|\uff5e|\ufe4f|\uffe5]+$/;

解释

上述表达式匹配了如下常见的中文标点符号:
。 ? ! , 、 ; : “ ” ‘ ‘ ( ) 《 》 〈 〉 【 】 『 』 「 」 ﹃ ﹄ 〔 〕 … — ~ ﹏ ¥

匹配邮箱地址

表达式

1
2
3
var reg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;

var reg = /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/

解释

前一种显式写明构成email地址的字符为字母大小写,数字和下划线;后一种使用‘\w’,简洁地表示了字符匹配,并且,考虑到了邮箱名有“.”连接的情况,比如:
gaochang.gcidea@gmail.com