什么是正则表达式

正则表达式描述了一种字符串匹配方式,包括一般字符(如a-z之间的字母)和特别字符(比方.、、$等有特别意义的专用字符)。

典型的查找和替换操作要求咱们供给与预期的查找成果匹配的切当文本。虽然这种技能对于对静态文本履行简略查找和替换使命或许现已足够了,但它缺少灵活性,若选用这种办法查找动态文本,即便不是不或许,至少也会变得很困难。 比方,需求验证用户输入的电话号码契合 ###-###-#### 格局(#表明一个数字)时,假如不运用正则表达式,则需求遍历用户输入的每个字符,确保#方位输入的是数字,非#方位输入的是-。而运用正则表达式的话,一行句子就能够完结验证功用。

// 不运用正则表达式验证输入
function isPattern(userInput) {
  if (typeof userInput !== 'string' || userInput.length !== 12) {
    return false;
  }
  for (let i = 0; i < userInput.length; i++) {
    let c = userInput[i];
    switch (i) {
      case 0:
      case 1:
      case 2:
      case 4:
      case 5:
      case 6:
      case 8:
      case 9:
      case 10:
      case 11:
        if (c < 0 || c > 9) return false;
        break;
      case 3:
      case 7:
        if (c !== '-') return false;
        break;
    }
  }
  return true;
}
// 运用正则表达式验证用户输入
function isPattern2(userInput) {
  return /^d{3}-d{3}-d{4}$/.test(userInput);
}

此外,一个好的正则表达式能够比非正则表达式更快地完结验证工作,如上述2种完成中,运用正则表达式的验证办法全体快于循环验证用户输入的办法。这便是正则表达式的强大之处。

正则表达式的主要功用包括:

  1. 进行数据验证:验证一个字符串是否契合某种方式,如电话号码方式或信用卡号码方式。
  2. 替换文本:能够运用正则表达式来识别文档中的特定文本,彻底删去该文本或许用其他文本替换它。
  3. 依据方式匹配从字符串中提取子字符串。

本文将先介绍正则表达式的两种匹配办法–字符匹配或方位匹配,然后对一种重要符号(括号)的运用进行总结,然后简略介绍正则表达式的匹配原理,并提出一些优化正则表达式的办法,最终经过3个事例展现正则表达式在实践场景中的运用。

字符匹配

正则表达式之所以强大,是由于其能完成含糊匹配来匹配字符串中的某种方式。而有些情况下,允许匹配多种方式中的一种,这时能够运用多选分支。下面咱们将详细介绍。

两种含糊匹配:量词和字符组

含糊匹配分为两个方向:横向含糊和纵向含糊。 横向含糊:被匹配字符串的呈现次数不是固定的。完成横向含糊的办法是运用量词 {m,n} ,表明前面的字符接连呈现最少m次,最多n次的方式。

var regex = /ab{2,5}c/g;
var string = "abc abbc abbbc abbbbc abbbbbc abbbbbbc";
console.log( string.match(regex) );
// => ["abbc", "abbbc", "abbbbc", "abbbbbc"] 匹配了b呈现2~5次的方式

量词的简写方式如下表:

量词简写 详细意义
{m,} 至少呈现m次
{m} 等价于{m,m},表明呈现m次
? 等价于{0,1},呈现一次或不呈现
+ 等价于{1,},至少呈现一次
* 等价于{0,},呈现恣意次或不呈现

纵向含糊:某一方位的字符不确定,有多种或许。完成纵向含糊的办法是运用字符组,如 [abc] ,表明该字符能够是a、b、c中的任何一个。

var regex = /a[123]b/g;
var string = "a0b a1b a2b a3b a4b";
console.log( string.match(regex) );
// => ["a1b", "a2b", "a3b"] 匹配了a和b中心是1、2、3的方式
  • 规模表明法:假如字符组中的字符特别多,能够运用规模表明法。如[123456abcdefGHIJKLM],能够写成 [1-6a-fG-M]。由于连字符在规模表明法中有特别用处,在作为一般字符进行匹配时,需求转义或许不放在两个字母之间,如要匹配“a”、“-”、“z”,能够运用 [az-][-az][a-z]
  • 排除字符组:能够用方括号中的尖号表明排除方括号中的选项。如 [^abc] 用于匹配除了a、b、c的其他值。
  • 为了简化书写,一些常用的字符组存在简写方式:
字符组简写方式 详细意义
d [0-9]。表明是一位数字。
D [^0-9]。表明除数字外的恣意字符。
w [0-9a-zA-Z_]。表明数字、大小写字母和下划线。
W [^0-9a-zA-Z_]。非单词字符。
s [tvnrf]。表明空白符,包括空格、水平制表符、笔直制表符、换行符、回车符、换页符。
S [^tvnrf]。 非空白符。
. [^nru2028u2029]。通配符,表明简直恣意字符。换行符、回车符、行分隔符和段分隔符除外。
  • 匹配恣意字符:通配符排除了换行符、回车符等,假如需求匹配恣意字符,能够运用 [dD][wW][sS][^] 中任何的一个。除此之外,在ES2018中增加了标志位s(“dotAll”),以使 . 能够匹配恣意字符,如 /foo.bar/s 中, . 就能够匹配换行符、回车符、行段分隔符。

上面说的纵向匹配都是匹配一个字符,假如需求匹配多个子方式中的恣意一个,能够运用多选分支。如 /p1 | p2 | p3/ 支撑匹配子方式p1或p2或p3中的恣意一个。

量词的两种匹配办法:贪婪匹配与慵懒匹配

量词的匹配默许是贪婪的,即会尽或许多的匹配。 举个,需求从下面的HTML中提出id="container"

<div id="container" class="main"></div>

假如将正则表达式写成 /id=".*"/ ,匹配到的内容将会是 id="container" class="main" 。由于通配符 . 能够匹配双引号,而量词 * 默许会进行贪婪匹配,当遇到 container 后边双引号时,是不会停下来,会持续匹配,直到遇到最终一个双引号为止。

解决这个问题的办法,便是运用慵懒匹配。

慵懒匹配(?):尽或许少的匹配,在量词后边加 ? 就能完成慵懒匹配。

慵懒匹配的量词 贪婪匹配的量词
{m,n}? {m,n}
{m,}? {m,}
?? ?
+? +
*? *

回到上面的比方,在量词 * 后边加 ? 完成慵懒匹配,会在遇到的第一个双引号处匹配成功。

// 贪婪匹配
var regex = /id=".*"/
var string = '<div id="container" class="main"></div>';
console.log(string.match(regex)[0]);
// => id="container" class="main"
// 慵懒匹配
var regex = /id=".*?"/
var string = '<div id="container" class="main"></div>';
console.log(string.match(regex)[0]);
// => id="container"

另外,多选分支在匹配时也是慵懒的,前面的子方式匹配上后就不会匹配后边的子方式了。

正则表达式方位匹配

什么是方位?

方位是相邻字符之间的方位。如下图所示,箭头所指的当地便是“hello”这个单词中的方位。方位的主要效果是替换和条件约束。方位自身无法匹配字符串的内容,可是能够为内容匹配供给约束条件。

正则表达式:运用、原理和优化

怎么匹配方位?

匹配方位是经过以下6个锚。在表格的第三列中,将对应锚匹配的方位替换成#,来可视化地展现锚匹配到的方位。

意义 用 # 替换锚匹配的方位
匹配行最初。多行匹配中匹配每行最初 “hello”.replace(/^/g, ‘#’);
// => “#hello”
$ 匹配行结束。多行匹配中匹配每行结束 “hello”.replace(/$/g, ‘#’);
// => “hello#”
b 匹配单词鸿沟,即 w 和 W 之间的方位 “[JS] Lesson_01.mp4”.replace(/b/g, ‘#’);
// => “[#JS#] #Lesson_01#.#mp4#”
B 匹配非单词鸿沟,即一切 b 不匹配的方位 “[JS] Lesson_01.mp4”.replace(/B/g, ‘#’);
// => “#[J#S]# L#e#s#s#o#n#_#0#1.m#p#4”
(?=p) 匹配子方式 p 前面的方位 “hello”.replace(/(?=l)/g, ‘#’);
// => “he#l#lo”
(?!p) 匹配一切 (?=p) 不匹配的方位 “hello”.replace(/(?!l)/g, ‘#’);
// => “#h#ell#o#”
(?<=p) 匹配子方式 p 后边的方位(ES2018) “hello”.replace(/(?<=l)/g, ‘#’);
// => “hel#l#o”
(?<!p) 匹配一切 (?<=p) 不匹配的方位(ES2018) “hello”.replace(/(?<!l)/g, ‘#’);
// => “#h#e#llo#”

了解方位

能够将方位了解为空字符“”,因而将字符之间的方位写成多个不会影响匹配。 如 /^^hello$$$//(?=he)^^he(?=w)llo$bb$/ 都能够匹配”hello”。

正则表达式括号的效果

分组和分支

括号是正则表达式中的重要符号。在正则表达式中括号主要有2种效果:分组和分支。

前面提到 (p1|p2) 表明匹配p1或p2,这是分支的效果。

括号分组的功用则愈加强大,支撑进行数据提取和替换操作。以 /(d{4})-(d{2})-(d{2})/ 为例,每个被括号中内容匹配到的子串都能够运用以下3种办法之一被提取出来。

提取办法 示例
字符串的match办法。
得到的数组中,下标1处的是从第一组提出的子串,下标2处的是从第二组提出的子串,以此类推。
var regex = /(d{4})-(d{2})-(d{2})/;
var string = “2017-06-12”;
console.log( string.match(regex) );
// => [“2017-06-12”, “2017”, “06”, “12”, index: 0, input: “2017-06-12”]
正则实例方针的exec办法。
得到的数组中,下标1处的是从第一组提出的子串,下标2处的是从第二组提出的子串,以此类推。
var regex = /(d{4})-(d{2})-(d{2})/;
var string = “2017-06-12”;
console.log( string.match(regex) );
// => [“2017-06-12”, “2017”, “06”, “12”, index: 0, input: “2017-06-12”]
结构函数的大局特点$1~$9。
$1表明从第一组提出的子串,$2表明从第二组提出的子串,以此类推。
var regex = /(d{4})-(d{2})-(d{2})/;
var string = “2017-06-12”;
regex.test(string); // 正则操作即可,例如
//regex.exec(string);
//string.match(regex);
console.log(RegExp.$1); // “2017”
console.log(RegExp.$2); // “06”
console.log(RegExp.$3); // “12”

在替换操作中运用捕获组捕获的内容:在replace函数中,能够经过$1获取第一个分组捕获的内容,经过$2获取第二个分组捕获的内容,以此类推。

比方需求将 yyyy-mm-dd 格局的日期,替换成 mm/dd/yyyy 格局。

var regex = /(d{4})-(d{2})-(d{2})/;
var string = "2017-06-12";
var result = string.replace(regex, "$2/$3/$1");
console.log(result);
// => "06/12/2017"

反向引证

有时需求在正则自身里引证之前呈现的分组,用于描述前后两部分内容共同的方式,这是反向引证。

在正则中, 1 表明前面从头开端的第1个分组,2 表明前面从头开端的第2个分组,以此类推。

如需求写一个匹配三种日期格局的正则:2016-06-122016/06/122016.06.12。最先想到的或许是 /d{4}(-|/|.)d{2}(-|/|.)d{2}/ ,前两个数字和后两个数字之间的分隔符或许是-/.。可是这个正则表达式也能匹配前后两个分隔符不共同的情况,如 2016-06/12

对于这种需求前后两个分隔符保持共同的方式,能够运用反向引证结构正则表达式:/d{4}(-|/|.)d{2}1d{2}/ 。1,表明的引证之前的那个分组 (-|/|.) 。不论它匹配到什么(比方 -),1 都匹配那个相同的详细某个字符。

一些问题

  • 括号嵌套时,怎么确定分组次序? 分组次序以左括号为准,左括号在前的分组次序在前。如 /^((d)(d(d)))1234$/ 中,第一个左括号对应的分组((d)(d(d)))是第一个分组(1);第二个左括号对应的分组 (d) 是第二个分组(2)……
  • 分组后有量词会怎么样? 分组捕获到的数据是括号中内容的最终一次匹配。
var regex = /(d)+/;
var string = "12345";
console.log( string.match(regex) );
// => ["12345", "5", index: 0, input: "12345"]

此刻反向引证引证的也是括号中内容的最终一次匹配。

var regex = /(d)+ 1/;
console.log( regex.test("12345 1") );
// => false
console.log( regex.test("12345 5") );
// => true

非捕获括号

上述括号都会捕获它们匹配的数据,以便后续引证。假如只想运用括号最原始的功用,但不捕获括号内容,也不会引证括号捕获的内容,能够运用非捕获括号 (?:p)(?:p1|p2|p3)

比方 /(?:d{4})-(?:d{2})-(?:d{2})/.exec("2017-06-12") 就不会捕获到“2017”、“06”和“12”,而 /(d{4})-(d{2})-(d{2})/.exec("2017-06-12") 会。

正则表达式回溯法原理

正则表达式匹配字符串的办法是回溯法。回溯法的实质是深度优先查找算法,即从问题的初始状况动身,查找从这种状况动身能达到的一切状况,当一条路无法再行进时,撤退一步或若干步(回溯),从另一种或许的状况再动身,持续查找,直到一切状况都试探过或许匹配完结。了解正则表达式的匹配原理有助于咱们写出高效的正则表达式,防止不必要的回溯。

量词的贪婪匹配

量词在贪婪匹配时,会从多到少测验,即先测验匹配呈现最多的或许性,匹配不成功时再回退,重新测验呈现较少的或许性。

假定正则是 /ab{1,3}c/ 。当方针字符串为”abbbc”时,匹配进程就没有回溯。由于量词的匹配默许是贪婪的,会优先匹配a和c之间有3个b的或许性,而方针字符串满意这种方式,故能够一次匹配成功。

正则表达式:运用、原理和优化
而当方针字符串为”abbc”时,匹配进程就会存在回溯。由于第一次试图匹配abbbc的测验失利了,所以回退一步,测验匹配a和c之间只要2个b的情况。
正则表达式:运用、原理和优化
图中第 5 步表明匹配不成功。此刻 b{1,3} 现已匹配到了 2 个字符 “b”,准备测验第三个时, 成果发现接下来的字符是 “c”。那么就认为 b{1,3} 就现已匹配完毕。然后状况又回到之前的状况(即第 6 步与第 4 步一样),最终再用子表达式 c,去匹配字符 “c”。此刻整个表达式匹配成功了。

图中的第 6 步,从第一个不匹配方式的字符回退的进程便是“回溯”。

量词的慵懒匹配

量词在慵懒匹配时,会首先测验匹配呈现次数最少的或许性,假如此刻全体无法匹配,那么会回退,测验匹配呈现次数第二少的或许性,看这样能否完结全体的匹配。如:

var string = "12345";
var regex = /^(d{1,3}?)(d{1,3})$/;
console.log( string.match(regex) );
// => ["12345", "12", "234", index: 0, input: "12345"]

匹配进程如下图:

正则表达式:运用、原理和优化

分支结构的匹配

分支结构也是慵懒的,在匹配进程中会早年往后挨个测验,假如前面的满意了,后边就不会再试验了。

可是当时面的分支结构形成了局部匹配,接下来表达式全体却不匹配时,仍会持续测验剩下的分支。这种测验也能够当作一种回溯。

如正则表达式 /^(can|candy)$/ ,方针字符串为“candy”,匹配进程如下:

正则表达式:运用、原理和优化

正则表达式的优化

了解了正则表达式的匹配原理后,就能够对咱们写出的正则表达式进行优化。

运用详细的字符组替代通配符来消除回溯

如方针字符串为 “abc”de ,假如运用 /".*"/ 进行匹配的话,虽然也能够正确匹配到”abc”,可是会比运用 /"[^"]*"/ 多发生2次回溯。由于通配符 . 能够匹配双引号,而量词的匹配默许是贪婪的,因而 .* 会匹配尽或许多的字符,而不会在第二个双引号处停下。可是 [^"] 不会匹配双引号,所以会在第二个双引号处中止匹配。

正则表达式:运用、原理和优化

运用非捕获型分组:削减空间占用

括号的效果之一是捕获分组和分支里的数据,捕获的内容需求内存来保存。因而,当不需求运用分组引证和反向引证时,能够运用非捕获分组。

/^[-]?(d.d+|d+|.d+)$/ 能够修正成 /^[-]?(?:d.d+|d+|.d+)$/

不同言语的正则表达式

不同言语中,正则表达式的基础用法相同,可是由于运用的正则表达式引擎不同,不同言语的正则表达式用法会稍有差异。比方PHPJavaScript中的正则表达式功用有不同之处,由于PHP运用PCRE引擎,而JavaScript运用ECMA规范。不同的正则表达式引擎完成了不同的功用集合,且时空功率有所不同。

各正则表达式引擎供给的功用比照详见正则表达式引擎比照表。

JavaScript中的正则相关API

JavaScript有8个与正则相关的API,其间5个是字符串实例上的API,3个是正则表达式实例上的API。

实例 API 根本用法 比方
String search 用于检索字符串中指定的子字符串,并回来子串的起始方位。
可运用字符串作为参数,参数会自动转换为正则表达式。
‘https://google.com’.search(/^https://.*/)
// 0
split 用于把一个字符串分割成字符串数组。回来分割后的字符串数组。 ‘2022-10-7 14:00’.split(/[-s:]/)
// [‘2022′, ’10’, ‘7’, ’14’, ’00’]
match 用于在字符串内检索指定的值。回来存放匹配成果的数组。该数组的内容依赖于正则表达式是否具有大局标志 g。 假如没找到匹配成果回来 null 。 ‘https://google.com’.match(/^https://.*/)
// [‘https://google.com’, index: 0, input: ‘https://google.com’]
replace 用于在字符串顶用一些字符串替换指定字符串,回来替换后的字符串。 ‘2022-10-7 14:00’.replace(/[s:]/g, ‘-‘)
// ‘2022-10-7-14-00’
matchAll 回来一个包括一切匹配正则表达式和分组捕获成果的遍历器。通常用循环从遍历器中取出匹配成果。正则表达式必须设置大局修饰符g,不然会报错。 for (const match of ‘abcabc’.matchAll(/a/g)) { console.log(match) }
// [ ‘a’, index: 0, input: ‘abcabc’, groups: undefined ]
// [ ‘a’, index: 3, input: ‘abcabc’, groups: undefined ]
RegExp test 用于检测一个字符串是否匹配某个方式,假如字符串中含有匹配的文本,则回来 true,不然回来 false。 /^https://.*/.test(‘https://google.com’)
// true
exec 用于检索字符串中的正则表达式的匹配。该函数回来一个数组,其间存放匹配的成果。假如未找到匹配,则回来值为 null。 /^https://.*/.exec(‘https://google.com’)
// [‘https://google.com’, index: 0, input: ‘https://google.com’]
toString 回来正则表达式的字符串值。 new RegExp(“a”, “g”).toString()
// ‘/a/g’

⚠️ 注意事项

  • match回来成果的格局,与正则方针是否有修饰符g有关:
    • 没有g时,回来的是规范匹配格局,即数组的第一个元素是全体匹配的内容,接下来是分组捕获的内容,然后是全体匹配的第一个下标,最终是输入的方针字符串。
    • g时,回来的是一切匹配的内容,不包括下标。
var string = "2017.06.27";
var regex1 = /b(d+)b/;
var regex2 = /b(d+)b/g;
console.log( string.match(regex1) );
console.log( string.match(regex2) );
// => ["2017", "2017", index: 0, input: "2017.06.27"]
// => ["2017", "06", "27"]
  • execmatch更强大:match带修饰符g时,就不回来关键信息index了,而exec办法能够解决这个问题。
var string = "2017.06.27";
var regex2 = /b(d+)b/g;
var result;
while ( result = regex2.exec(string) ) {
    console.log( result, regex2.lastIndex );
}
// => ["2017", "2017", index: 0, input: "2017.06.27"] 4
// => ["06", "06", index: 5, input: "2017.06.27"] 7
// => ["27", "27", index: 8, input: "2017.06.27"] 10

此外,不带修饰符g时,虽然matchexec在履行成果上是等效的,可是exec在操控台中会提早履行,而match由于或许有副效果,在Chrome操控台中就不会提早履行。比方在操控台输入 /123/.exec('123456') ,即便不回车也能看到履行成果;而输入'123456'.match(/123/),只要回车之后才能看到履行成果。在操控台中反复调整比较杂乱的正则表达式时,假如运用 match ,就需求不断回车、上箭头、修正、回车了,因而用 exec 能稍微快一点。

  • 修饰符gexectest函数的影响:带修饰符g时,正则表达式方针会有一个lastIndex特点表明前次匹配成果的后一个方位,每次匹配都会从lastIndex开端匹配,即便匹配的字符串不相同;而不带g时,都是从字符串第0个字符处开端匹配。下面代码中的第三次调用 test,由于这一次测验匹配,开端从下标 lastIndex,即 3 方位处开端查找,因而就找不到了。
var regex = /a/g;
console.log( regex.test("a"), regex.lastIndex );
console.log( regex.test("aba"), regex.lastIndex );
console.log( regex.test("ababc"), regex.lastIndex );
// => true 1
// => true 3
// => false 0

实践事例

一. 数字格局化

将数字转换为带千位分隔符的方式:如把 “12345678”,变成 “12,345,678”。

  1. 参加逗号:运用 /(?=(d{3})+$)/g 在每3位数字之前参加逗号。其间 (d{3})+$ 表明从结束向前的3个、6个、9个……数字, /(?=(d{3})+$)/ 表明从结束向前的3个数字之前的方位、6个数字之前的方位、9个数字之前的方位……。
var result = "12345678".replace(/(?=(d{3})+$)/g, ',')
console.log(result);
// => "12,345,678"
  1. 去掉最初的逗号:运用上述正则多验证几个事例就会发现,一旦数字长度是3的倍数,就会在数字前面的方位也加上逗号,因而需求匹配到的方位不能是最初。能够用 (?!^) 表明匹配最初以外的方位。
var regex = /(?!^)(?=(d{3})+$)/g;
var result = "12345678".replace(regex, ',')
console.log(result);
// => "12,345,678"
result = "123456789".replace(regex, ',');
console.log(result);
// => "123,456,789"
  1. 支撑字符串包括多个数字的情况:如要把 “12345678 123456789” 替换成 “12,345,678 123,456,789″。直接将 (?!^) 换成 (?!b) 即可,表明匹配的方位不能是单词鸿沟。而 B 自身表明非单词鸿沟的方位,因而能够将 (?!b) 进一步简化为 B
var string = "12345678 123456789",
regex = /(?!b)(?=(d{3})+b)/g;
var result = string.replace(regex, ',')
console.log(result);
// => "12,345,678 123,456,789"

二. 表单校验-验证暗码

表单校验是正则表达式最常见的运用场景。 用户输入中暗码设置的常见要求是:暗码长度 6-12 位,由数字、小写字母和大写字母组成,但必须至少包括 2 种字符。 咱们能够先简化这个条件:

  1. 匹配6~12位,由数字、小写字母和大写字母组成的暗码的正则表达式很简略: /^[0-9A-Za-z]{6,12}$/
  2. 满意条件1,可是只要求必须包括1种指定字符:比方只要求必须包括数字,能够运用 (?=.*[0-9])^ ,即最初处、后边的字符串匹配“任何多个恣意字符,后边有一个数字”这一方式的前面的方位:/(?=.*[0-9])^[0-9A-Za-z]{6,12}$/
  3. 满意条件1,可是要求必须一起包括2种指定字符:如必须一起包括数字和小写字母,能够运用2个2中的方位匹配方式进行约束 (?=.*[0-9])(?=.*[a-z])/(?=.*[0-9])(?=.*[a-z])^[0-9A-Za-z]{6,12}$/

现在来匹配完好的暗码方式。能够把“必须至少包括2种字符”的要求变成:一起包括数字和小写字母,或一起包括数字和大写字母,或一起包括小写字母和大写字母。因而校验暗码的正则表达式能够写成:

var regex = /((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[a-z])(?=.*[A-Z]))^[0-9A-Za-z]{6,12}$/;
console.log( regex.test("1234567") ); // false 满是数字
console.log( regex.test("abcdef") ); // false 满是小写字母
console.log( regex.test("ABCDEFGH") ); // false 满是大写字母 
console.log( regex.test("ab23C") ); // false 缺乏6位 
console.log( regex.test("ABCDEF234") ); // true 大写字母和数字 
console.log( regex.test("abcdEF234") ); // true 三者都有
  • 另一种解法:“至少包括两种字符”也能够了解为,不能全都是数字,也不能全都是小写字母,也不能全都是大写字母,因而也能够写成以下方式
var regex = /(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/;
console.log( regex.test("1234567") ); // false 满是数字
console.log( regex.test("abcdef") ); // false 满是小写字母
console.log( regex.test("ABCDEFGH") ); // false 满是大写字母
console.log( regex.test("ab23C") ); // false 缺乏6位 
console.log( regex.test("ABCDEF234") ); // true 大写字母和数字 
console.log( regex.test("abcdEF234") ); // true 三者都有

三. 表单校验-验证邮箱

RFC 5322:Internet Message Format规范中定义了邮箱地址规范,依据RFC5322规范编写的邮箱校验正则表达式如下:

正则表达式:运用、原理和优化
正则表达式:运用、原理和优化
这个正则表达式包括2个部分:@前的部分和@后的部分。 @前的部分允许2种方式:

  1. 一系列字母、数字和特定符号,包括一个或多个点。可是点不能接连呈现,或许呈现在邮箱地址的第一位或最终一位。
  2. 用双引号括起来,允许任何ASCII码字符呈现在双引号中,可是空白字符、双引号和反斜杠必须运用反斜杠转义。

@后的部分也允许2种方式:

  1. 一个完好域名,如regular-expressions.info
  2. 用方括号括起来的IP地址或其他或许的路由地址(需求阐明的是,虽然RFC5322中规定域名字面量能够包括不行打印字符,可是目前并没有在任何规范中看到为什么不行打印字符必须呈现在 (?:(?: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]?|[a-z0-9-]*[a-z0-9]: 之后。因而这个正则表达式的最终一部分还有待考证,欢迎大家补充阐明)。

虽然这是由官方规范定义的邮箱地址方式,可是并不引荐运用它来校验用户输入,由于接纳输入的运用自身或许无法处理契合这个方式的一切邮箱地址。如其他或许的路由地址或许包括不行打印的ASCII字符,或许在运用中形成显示问题;再比方不是一切运用都支撑在@前运用双引号或在@后运用方括号。

假如不论IP地址和其他特别的路由地址,不支撑双引号和方括号呈现在邮箱地址中,能够将邮箱地址校验正则简化为如下方式:

正则表达式:运用、原理和优化
最终,在长度方面,RFC 5322规范阐明晰@前的local部分最大长度为64字符,每个域名的最大长度为63字符,可是并未对全体长度进行约束。而电子邮件传输协议SMTP协议能处理的最大邮箱地址长度是254个字符,因而,在上面邮箱地址方式中参加对长度的考虑能够得到以下邮箱地址校验方式。
正则表达式:运用、原理和优化

  • 咱们需求这么杂乱的邮箱地址校验办法吗?

假定用户输入了一个邮箱地址john.doe@somewhere.com。这个邮箱契合RFC 5322规范,能够经过校验,可是这并不能确保这个邮箱地址存在并能够接纳邮件,除非你真正向这个地址成功发送了一封邮件。因而,假如咱们最终都得经过发送邮件来承认一个邮箱地址是否存在,能够运用更简略的正则表达式来校验输入,在确保不会回绝任何已存在的邮箱地址的情况下,尽或许削减非法邮箱输入。

比方能够运用浏览器在 <input type="email" placeholder="Enter your email" /> 顶用于校验输入的正则表达式:

/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/

参考资料

  • JavaScript正则表达式迷你书(第一版)
  • regular-expressions-Email-Address
  • Regular Expressions Cookbook, 2nd Edition by Jan Goyvaerts, Steven Levithan
  • How to Use Regular Expressions in JavaScript – Tutorial for Beginners
  • Crate email_address Email Address Regular Expression That 99.99% Works.
  • <input type="email">

正则表达式相关东西网站

  • 正则表达式可视化:引荐三款正则可视化东西
  • 比照正则表达式和非正则表达式的履行功能:JSBench.me