正则表达式详解

发布于:2025-03-09 ⋅ 阅读:(76) ⋅ 点赞:(0)


代码,是前端工程师的“武器”,也是他们的“面包和黄油”。


一、基本概念

正则表达式(regular expression)描述了字符的模式对象。

1.基本语法

var patt=new RegExp(pattern,modifiers);
var patt=/pattern/modifiers;


// 参数
.pattern 模式,描述了表达式的模式
.modifiers 修饰符,检索是否是全局,区分大小写等

2.修饰符

修饰符用于执行区分大小写和全局匹配

修饰符 描述
i 执行对大小写不敏感的匹配。
g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
m 执行多行匹配。

3.方括号

方括号用于查找某个范围内的字符

表达式 描述
[abc] 查找方括号之间的任何字符。
[^abc] 查找任何不在方括号之间的字符。
[0-9] 查找任何从 0 至 9 的数字。
[a-z] 查找任何从小写 a 到小写 z 的字符。
[A-Z] 查找任何从大写 A 到大写 Z 的字符。
[A-z] 查找任何从大写 A 到小写 z 的字符。
[adgk] 查找给定集合内的任何字符。
[^adgk] 查找给定集合外的任何字符。
(red blue

4.元字符

元字符(Metacharacter)是拥有特殊含义的字符:

元字符 描述
. 查找单个字符,除了换行和行结束符。
\w 查找数字、字母及下划线。
\W 查找非单词字符。
\d 查找数字。
\D 查找非数字字符。
\s 查找空白字符。
\S 查找非空白字符。
\b 匹配单词边界。
\B 匹配非单词边界。
\0 查找 NULL 字符。
\n 查找换行符。
\f 查找换页符。
\r 查找回车符。
\t 查找制表符。
\v 查找垂直制表符。
\xxx 查找以八进制数 xxx 规定的字符。
\xdd 查找以十六进制数 dd 规定的字符。
\uxxxx 查找以十六进制数 xxxx 规定的 Unicode 字符。

5.量词

量词 描述
n+ 匹配任何包含至少一个 n 的字符串。
n* 匹配任何包含零个或多个 n 的字符串。
n? 匹配任何包含零个或一个 n 的字符串。
n{X} 匹配包含 X 个 n 的序列的字符串。
n{X,} X 是一个正整数。前面的模式 n 连续出现至少 X 次时匹配。
n{X,Y} X 和 Y 为正整数。前面的模式 n 连续出现至少 X 次,至多 Y 次时匹配。
n$ 匹配任何结尾为 n 的字符串。
^n 匹配任何开头为 n 的字符串。
?=n 匹配任何其后紧接指定字符串 n 的字符串。
?!n 匹配任何其后没有紧接指定字符串 n 的字符串。
^                   from the start of the input
(?=.*\d)            assert one or more digits are present
(?=.*[a-z])         assert lowercase letters
(?=.*[A-Z])         assert uppercase letters
(?=.*[^a-zA-Z0-9])  assert one or more characters which are NOT alphanumeric
(?!.*\s)            assert one or more whitespace characters

二、结构

1.匹配模式

精确匹配应用比较局限,匹配数据比较少;模糊匹配结果可能性更多,能够满足更多场景

var regex = /hello/; // 精确匹配
regex = /^hello$/; // 精确匹配 + 完全匹配
regex = /hel{2}o/; // 模糊匹配 + 横向模糊(重复)
regex = /hel[lk]o/; // 模糊匹配 + 纵向模糊(该位置有多种可能)([lk]只占据一个位置)
console.log( regex.test("hello") );

2.字符组

字符组归纳了一连串的字符或者枚举值

// 正向字符组
12345可以表示成[1-5],该规范默认会被识别成字符组([-15]就不会被识别成字符组)
bcdefg可以表示成[b-g]


// 取反字符组
[^1-5]表示除了12345以外的字符


// 字符组简写
数字:\d 表示 [0-9];\D 表示 [^0-9]
单词(数字、字母、下划线):\w 表示 [a-zA-Z0-9_];\W 表示 [^a-zA-Z0-9_]
空白符(空白符,包括空格、水平制表符、垂直制表符、换行符、回车符、换页符):
\s 表示 [ \t\v\n\r\f];\S 表示 [^ \t\v\n\r\f]; // 注意空格
. 表示 任意字符

3.量词

假设匹配数量是num

{m} 表示 num = m
{m,} 表示 m <= num
{m, n} 表示 m <= num <= m
? 表示 0 <= num <= 1
+ 表示 1 <= num
* 表示 0 <= num

4.贪婪匹配和惰性匹配

默认贪婪匹配,量词后加?表示惰性匹配
{m, n} + 贪婪匹配 === n
{m, n}? + 惰性匹配 === m

var regex = /\d{2,5}/; // 12345
regex = /\d{2,5}?/; // 12
const string = "123456";
console.log(string.match(regex) );

5.多选分支

var regex = /red|color/g;
var string = "red yellow color"; // 示范值 [red, color]
string = "redcolor"; // red 匹配到了不会再选择领一个分支;分支也是默认惰性
console.log(string.match(regex) );

6.匹配模式关键词

g 表示 全局匹配,类似于贪婪匹配,匹配到一个满足条件的,不会停止,继续往下匹配
i 表示 忽略大小写
m 表示 多行,针对有\n换行符的字符串

三、位置

在这里插入图片描述

1.位置锚点

^ 表示 匹配开头,在多行匹配中匹配行开头
$ 表示 匹配结尾,在多行匹配中匹配行结尾
\b 表示 单词边界(单词左右两边和非单词的位置)
\B 表示 非单词边界(单词内部的字符之间的位置)
(?=key) 表示 key的一个子模式,表示key前面的那个位置
(?!key) 表示 key的一个子模式,表示不是key前面的那个位置
(?<=key) 表示 key的一个子模式,表示key后面的那个位置
(?<!key) 表示 key的一个子模式,表示不是key后面的那个位置

案例

// 空格匹配
console.log("hello".replace(/^|$/g, '#')); // #hello#
// 多行匹配
console.log("hello\nworld".replace(/^|$/gm, '#')); // #hello##world# m表示多行
// 单词边界
"world+".replace(/\b/g, '#') // #world#+ 注意头部和尾部和单词之间也算一个边界
// o前面的位置
"world+".replace(/(?=o)/g, '#') // w#orld+
// o后面的位置
"world+".replace(/(?<=o)/g, '#') // wo#rld+

2.分组与引用

括号在正则中的功能就是用于分组(字符的集合)。简单来理解就是,由多个元字符组成某个部分,应该被看成一个整体的时候,可以用括号括起来表示一个整体,这是括号的一个重要功能。其实用括号括起来还有另外一个作用,那就是“复用”。

/1(1|2)/g.test("12") // true
"121213".match(/1(1|2)/g) // [12, 12]
"121213".match(/1(1|2)+/g) // [1212] +号会让他变成贪婪匹配

1.分组与编号

括号在正则中可以用于分组,被括号括起来的部分“子表达式”会被保存成一个子组。

那分组和编号的规则是怎样的呢?其实很简单,用一句话来说就是,第几个括号就是第几个分组。
在这里插入图片描述

2.不保存子组

在括号里面的会保存成子组,但有些情况下,你可能只想用括号将某些部分看成一个整体,后续不用再用它,类似这种情况,在实际使用时,是没必要保存子组的。这时我们可以在括号里面使用 ?: 不保存子组。

如果正则中出现了括号,那么我们就认为,这个子表达式在后续可能会再次被引用,所以不保存子组可以提高正则的性能。
在这里插入图片描述

const regex = /(?:\d{4})-(\d{2})-(\d{2})/;
const str = "1990-12-17";
const match = regex.exec(str);


if (match !== null) {
  console.log(`Month: ${match[1]}`);
  console.log(`Day: ${match[2]}`);
} else {
  console.log("No date found.");
}

在这个例子中,年份的捕获组被转换为一个非捕获组,因此它不会出现在 match 数组中。这样,match[1] 直接引用月份,而不是年份。

3.括号嵌套

在括号嵌套的情况里,我们要看某个括号里面的内容是第几个分组怎么办?只需要数左括号(开括号)是第几个,就可以确定是第几个子组。
在这里插入图片描述

日期分组编号是 1,时间分组编号是 5,年月日对应的分组编号分别是 2,3,4,时分秒的分组编号分别是 6,7,8。

// 从左到右读取,碰到括号进入括号,再从左到右读取
"123".replace(/(\d(\d(\d)))/, "$1-$2-$3") // 123-12-3

4.命名捕获组

在一些编程语言中还提供了命名分组,命名分组格式为(?<分组名>正则)。

const regex = /(?<group1>\w+)\s+(?<group2>\w+)/;
const result = regex.exec("Hello World");


console.log(result.groups.group1); // 输出 "Hello"
console.log(result.groups.group2); // 输出 "World"

5.引用捕获组

在知道了分组引用的编号 (number)后,大部分情况下,就可以使用 “反斜扛 + 编号”,即 \number 的方式来进行引用,而 JavaScript 中是通过$编号来引用的,如$1。

// 正则中的分组引用 === \index 如\1, \2
"1231213".match(/(12)\d\1/g) // 12312   \1 表示分组变量 (12)
// 替换变量 $ + index
"12123".replace(/(12)(123)/g, "$2$1") // $1 表示分组变量 (12) $2 表示分组变量 (123)


// 分组全部替换
// $1 === 123; $2 === 12
// str被reg匹配为123 12 123 12,剩余字符串为‘’,直接替换
str = '123 12 123 12'
reg = /(123) (12) \1 \2/g
str.replace(reg, '$2-$1')
// return '12-123'


// 分组部分替换
// str被reg匹配为12 123,剩余字符串为'124 {regStr} 12'
// 12-123替换regStr,最终为'124 12-123 12'
str = '124 12 123 12'
reg = /(123)?(12) \1/g
str.replace(reg, '$2-$1')
// return '124 12-123 12'

3.回溯匹配

"12223".match(/12{1,3}3/) // 匹配5步就结束了
// 无回溯;匹配1,匹配2子模式,匹配3,顺利结束


"1223".match(/12{1,3}3/) // 1223
// 匹配到122以后,第4步在第四个位置,依然匹配字符串2,发现是3,于是回到上一步的状态,结束2{1,3}子模式
// 第5步回溯
// 第6步开始对3的匹配,在第四个位置匹配3,找到了,结束字符串3的匹配

四、对象方法

方法 描述
compile 在 1.5 版本中已废弃。 编译正则表达式。
exec 检索字符串中指定的值。返回找到的值,并确定其位置。
test 检索字符串中指定的值。返回 true 或 false。
toString 返回正则表达式的字符串。

支持正则表达式的 String 对象的方法

方法 描述 FF IE
search 检索与正则表达式相匹配的值。 1 4
match 找到一个或多个正则表达式的匹配。 1 4
replace 替换与正则表达式匹配的子串。 1 4
split 把字符串分割为字符串数组。 1 4

RegExp 对象属性

属性 描述
constructor 返回一个函数,该函数是一个创建 RegExp 对象的原型。
global 判断是否设置了 “g” 修饰符
ignoreCase 判断是否设置了 “i” 修饰符
lastIndex 用于规定下次匹配的起始位置
multiline 判断是否设置了 “m” 修饰符
source 返回正则表达式的匹配模式

1.test 方法

test()方法搜索字符串指定的值,根据结果并返回真或假。

var patt1=new RegExp("e");
patt1.test("The best things in life are free")


var str = 'runoob';
var patt1 = new RegExp('\\w', 'g'); // 有转义作为正则表达式处理
var patt2 = new RegExp('\w', 'g');  // 无转义作为字符串处理
var patt3 =/\w+/g;  // 与 patt1 效果相同


patt1.test(str) // 输出 true
patt2.test(str) // 输出 false
patt3.test(str) // 输出 true

2.exec 方法

exec() 方法用于在字符串中执行搜索匹配,它接受一个字符串作为参数,并返回一个数组,该数组表示匹配的结果。如果没有找到匹配,则返回 null。

let match = regExp.exec(str)

其中,regExp是一个正则表达式对象,str是要在其中执行搜索的字符串参数。

返回值结构

  • [0]:匹配到的整个字符串

  • [1] 及其他(从索引1开始):捕获组的内容(如果正则表达式使用了捕获组,如 ())

  • index:匹配的开始位置(在原字符串中的起始索引)

  • input:被搜索的原字符串

  • groups:一个对象,包含所有命名捕获组的匹配内容(如果有使用命名捕获组)

使用exec方法可以执行有限次数的全局搜索,并每次返回一个匹配项。下次执行时,它会从上一次匹配项的后面继续搜索。

逐步匹配

exec()方法的一个强大之处在于,它可以用于逐步匹配字符串中的多个匹配项。通过在一个循环中反复调用exec(),我们可以逐个处理每个匹配项,直到没有更多的匹配项为止。

const regex = /ab*/g;
const str = "abbcdefabhijkab";
let match;


while ((match = regex.exec(str))) {
  console.log(`匹配到的文本:${match[0]}`);
  console.log(`匹配项在字符串中的起始位置:${match.index}`);
}


// 输出结果:
// 匹配到的文本:abb
// 匹配项在字符串中的起始位置:0
// 匹配到的文本:ab
// 匹配项在字符串中的起始位置:7
// 匹配到的文本:ab
// 匹配项在字符串中的起始位置:14

捕获组与子匹配项

捕获组(Capturing Groups)通过括号 () 来定义,它可以匹配并提取部分字符串。每个括号内的表达式都是一个捕获组,可以捕获与之匹配的文本。

这些捕获组的结果将作为返回数组的后续元素(从索引1开始)出现。这使得我们可以轻松地访问和处理匹配项中的子部分。

let regex = /(\d+)\s(\w+)/;  // 匹配:数字 空格 字母组合
let result = regex.exec("123 abc");
console.log(result);


// 输出结果
[
  '123 abc',  // 整个匹配的字符串
  '123',      // 捕获组 1:数字部分
  'abc',      // 捕获组 2:字母部分
  index: 0,   // 匹配开始的索引
  input: '123 abc'
]

命名捕获组

**命名捕获组的优势:**命名捕获组(使用 (?pattern) 语法)可以让匹配结果更具可读性,特别是当你需要提取多个不同的部分时。

let regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let result = regex.exec("2023-09-24");
console.log(result);


// 输出结果:
[
  '2023-09-24',   // 匹配到的整个字符串
  '2023',         // 第一个捕获组:年份
  '09',           // 第二个捕获组:月份
  '24',           // 第三个捕获组:日期
  index: 0,       // 匹配的起始索引
  input: '2023-09-24',  // 被搜索的字符串
  groups: {       // 命名捕获组
    year: '2023',
    month: '09',
    day: '24'
  }
]

通过 groups 属性,你可以更方便地获取并使用这些命名捕获的结果,而不需要依赖捕获组的顺序。

全局匹配与lastIndex属性

当正则表达式包含全局标志(g)时,exec()方法的行为会发生变化。它将从lastIndex属性指定的位置开始搜索匹配项,并在找到匹配项后更新lastIndex的值。这使得我们可以在一个循环中逐步处理字符串中的所有匹配项。

let regex = /\d+/g;
let str = "123 456 789";
let result;


while ((result = regex.exec(str)) !== null) {
  console.log(result);
}


// 输出结果
[ '123', index: 0, input: '123 456 789' ]
[ '456', index: 4, input: '123 456 789' ]
[ '789', index: 8, input: '123 456 789' ]

每次调用 exec(),它会返回下一个匹配的结果,直到返回 null,表示没有更多匹配。

lastIndex 属性

在全局匹配模式下,正则表达式对象的 lastIndex 属性会记录下次匹配开始的位置。每次匹配后,lastIndex 会更新,帮助 exec() 从上次结束的位置继续匹配。

let regex = /\d+/g;
let str = "123 456 789";
let result = regex.exec(str);


console.log(result);  // 匹配 123
console.log(regex.lastIndex);  // 输出 3


result = regex.exec(str);
console.log(result);  // 匹配 456
console.log(regex.lastIndex);  // 输出 7

方法的比较

  • **test():**返回布尔值,表示正则表达式是否匹配字符串。

  • **match():**如果是非全局正则表达式,它与 exec() 类似,但全局正则时,它一次性返回所有匹配项。

  • **exec():**可以返回详细的匹配结果,包括捕获组和匹配位置。

let regex = /\d+/g;
let str = "123 456 789";


// 使用 exec() 逐步匹配
let result;
while ((result = regex.exec(str)) !== null) {
  console.log(result[0]);  // 依次输出 123, 456, 789
}


// 使用 match() 一次性匹配
let matches = str.match(regex);
console.log(matches);  // ['123', '456', '789']

常见错误

  • 忘记考虑全局标志和lastIndex:当使用全局正则时,exec() 会记住上次匹配结束的位置。如果不注意,可能导致跳过某些匹配。

  • 忽略捕获组:如果想提取特定内容但没有使用捕获组,匹配结果中就不会包含这些信息。

  • 没有处理命名捕获组:如果正则中使用了命名捕获组,但未正确访问 groups 属性,就无法获取命名捕获结果。

3.match 方法

match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。

stringObject.match(searchvalue)
stringObject.match(regexp)
参数 描述
searchvalue 必需。规定要检索的字符串值。
regexp 必需。规定要匹配的模式的 RegExp 对象。如果该参数不是 RegExp 对象,则需要首先把它传递给 RegExp 构造函数,将其转换为 RegExp 对象。
// 参数为searchvalue时:
var str="Hello world!"
str.match("world")  // ["world", index: 6, input: "Hello world!", groups: undefined]
str.match("World")  // null
str.match("worlld")  // null
str.match("world!") 
// 返回结果
[
  "world!", 
  index: 6, 
  input: "Hello world!", 
  groups: undefined
]


// 参数为正则表达式时:
var str=" mm -4193 1 with words"
str.match(/\d+/g) // ["4193", "1"]
str.match(/\d+/)  
// 未加全局时:
[
  "4193", 
  index: 5, 
  input: " mm -4193 1 with words", 
  groups: undefined
]


var str2="-6754 uuuid" //获取带符号的整数
str2.match(/^(-|\+)?\d+/) 
// 返回结果
[
  "-6754", "-", 
  index: 0, 
  input: "-6754 uuuid", 
  groups: undefined
]

无全局标志

当正则表达式不带 g 标志时,match() 只返回第一个匹配的字符串和其他相关的匹配信息。包括:

  • **groups:**一个捕获组对象或undefined(如果没有定义命名捕获组)

  • **index:**匹配的结果的开始索引位置

  • **input:**搜索的字符串

const text = "I have 2 cats and 3 dogs.";
const result = text.match(/(\d+)/);


console.log(result); 
// 输出: ["2", "2"]
  • result[0]:整个匹配(2)。

  • result[1]:捕获组中的匹配(2)。

带全局标志

使用 g 标志后,match() 会返回字符串与正则表达式匹配的所有结果组成的数组,如果没有匹配的字符串则返回null,但不会返回捕获组。

const text = "I have 2 cats and 3 dogs.";
const result = text.match(/\d+/g);


console.log(result);  
// 输出: ["2", "3"]

此时 match() 返回一个数组,包含了所有数字的匹配项 [“2”, “3”]。

特殊情况

**无匹配项:**如果正则表达式没有匹配到任何结果,match() 会返回 null。

const result = "hello".match(/\d+/);
console.log(result);  // 输出: null

**无全局标志但有捕获组:**当没有 g 标志且有捕获组时,match() 不仅返回整个匹配,还会返回所有捕获组的匹配。

const text = "The price is $100";
const result = text.match(/(\$\d+)/);
console.log(result);  
// 输出: ["$100", "$100"]
const str = 'Hello JavaScript'
str.match()  // [""]
str.match(/JS/) // null
str.match(/JavaScript/g)  // ["JavaScript"]
str.match(/JavaScript/)
// 返回结果
[
  0: "JavaScript", 
  groups: undefined, 
  index: 6, 
  input: "Hello JavaScript"
]
str.match(/(?<J>Java)(?<S>Script)/)
// 返回结果
[
  0: "JavaScript", 
  1: "Java", 
  2: "Script", 
  groups: { J: "Java", S: "Script" }, 
  index: 6, 
  input: "Hello JavaScript"
]

4.matchAll 方法

matchAll() 方法返回一个包含所有匹配正则表达式的结果及其分组捕获组的迭代器。

str.matchAll(reg)

**reg:**正则表达式对象。如果不是正则表达式则会使用new RegExp(obj)隐式转换为正则表达式。表达式必须设置为 g (全局模式)否则会报错

**返回值:**一个迭代器,可以使用for…of…,数组新增的扩展符(…)或Array.from()实现功能。

const str = 'hello javascript hello css'
console.log(...str.matchAll(/hello/g))
// [0: "hello", groups: undefined, index: 0, input: "hello javascript hello css"]
// [0: "hello", groups: undefined, index: 17, input: "hello javascript hello css"]


// 0: "hello"  匹配的字符串,如果有使用分组会在后面依次列出来
// groups: undefined  没有使用命名捕获组会返回undefined,否则会返回包含命名捕获组的对象
// index: 0  匹配的结果在当前字符串位置开始的索引
// input: "hello javascript hello css" 当前字符串

特殊情况

**没有全局标志 g:**如果正则表达式没有 g 标志,matchAll() 会抛出错误。

const text = "I have 2 cats and 3 dogs.";
const result = text.matchAll(/\d+/);  // 错误:没有 g 标志

**支持捕获组:**即使在没有 g 标志时,matchAll() 依然会返回所有捕获组。

特性 match() matchAll()
返回类型 数组(或ull) 迭代器(包含所有匹配及捕获组)
是否支持全局匹配 需要g标志才能去哪聚匹配 始终全局匹配,不需要g
捕获组支持 仅在无g标志时返回捕获组 始终返回所有捕获组
返回多个结果 仅在g标志时返回多个匹配项 始终返回多个匹配项和捕获组
返回的结果如何处理 只返回匹配项,捕获组不一定返回 返回匹配的所有详细信息,包含索引、捕获组等
使用场景 简单的正则匹配,适合单个结果或少量结果 复杂匹配,特别是需要捕获组和详细信息时

适用场景

match() 适用场景:

  • 当只需要找到第一个匹配结果或在简单的场景下查找所有匹配项时使用。

  • 不关心捕获组的详细信息,只关心匹配的值。

matchAll() 适用场景:

  • 当需要获取所有匹配项的详细信息,包括索引、捕获组时,matchAll() 更加合适。

  • 在涉及多个捕获组的复杂匹配场景中,使用 matchAll() 可以获得更多控制和信息。

5.总结

  • match() 用于简单匹配,它在没有 g 标志时返回第一个匹配及捕获组,而在有 g 标志时返回所有匹配项,但不包含捕获组。

  • matchAll() 提供了更强大的功能,返回一个包含所有匹配和捕获组的迭代器,适用于复杂匹配场景,特别是在处理多个捕获组时表现出色。

五、常见应用

1.合法IP地址

ip地址合法的标准是:a.b.c.d 是0255之间的十进制整数。IP地址是指互联网协议地址,是一个32位的二进制数,通常被分割为4个“8位二进制数”。IP地址通常用“点分十进制”,其中a.b.c.d应是0255之间的十进制整数。

iPv4的ip地址都是(1255).(0255).(0255).(0255)的格式。

A类的IP地址范围为0.0.0.0-127.255.255.255,B类的IP地址范围为128.0.0.0-191.255.255.255,C类的IP地址范围为192.0.0.0-223.255.255.255。

判断IP合法性:

1、IP地址是4个3位数用"."隔开的字串;

2、其中每个3位数都一定在0~255(含)之间,否则为非法;

3、IP地址也有内网与公网之分。

2.合法邮箱

邮箱的基本格式为:“用户名@域名”,用户名部分以字母和数字开头,可以包含字母、数字、点号(.)、下划线(_)和连字符(-),而域名部分可以包含字母、数字、点号(.)和连字符(-)。此外,域名部分还必须包含至少一个点号,以区分顶级域名和次级域名。如果邮箱的格式不符合这些规则,则可以判断邮箱不合法。

1、是否合法IP地址:
pattern:/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/,
 
2.是否手机号码或者固话
pattern:/^((0\d{2,3}-\d{7,8})|(1[34578]\d{9}))$/,
 
3. 是否身份证号码
pattern:/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/,
 
4.是否邮箱
pattern:/^([a-zA-Z0-9]+[-_\.]?)+@[a-zA-Z0-9]+\.[a-z]+$/,
 
5.整数填写
pattern:/^-?[1-9]\d*$/,
 
6.正整数填写
pattern:/^[1-9]\d*$/,
 
7.小写字母
pattern:/^[a-z]+$/,
 
8.大写字母
pattern:/^[A-Z]+$/,
 
9.大小写混合
pattern:/^[A-Za-z]+$/,
 
10.多个8位数字格式(yyyyMMdd)并以逗号隔开
pattern:/^\d{8}(\,\d{8})*$/,
 
11.数字加英文,不包含特殊字符
pattern:/^[a-zA-Z0-9]+$/,
 
12.前两位是数字后一位是英文
pattern:/^\d{2}[a-zA-Z]+$/,
 
13.密码校验(6-20位英文字母、数字或者符号(除空格),且字母、数字和标点符号至少包含两种)
pattern:/^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$)([^\u4e00-\u9fa5\s]){6,20}$/,


// 密码的强度必须是包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间。
pattern: /^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$/
 
14.中文校验
pattern:/^[\u0391-\uFFE5A-Za-z]+$/,


15.中文汉字校验
pattern:/^[/u4e00-/u9fa5]+$/,

参考:https://blog.csdn.net/maggie_live/article/details/85045868
https://blog.csdn.net/PersonalM/article/details/103783278

validator.js文件中常见的验证方法

1、是否合法IP地址
export function validateIP(rule, value,callback) {
  if(value==''||value==undefined||value==null){
    callback();
  }else {
    const reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
    if ((!reg.test(value)) && value != '') {
      callback(new Error('请输入正确的IP地址'));
    } else {
      callback();
    }
  }
}
 
2、是否手机号码或者固话
export function validatePhoneTwo(rule, value, callback) {
  const reg = /^((0\d{2,3}-\d{7,8})|(1[34578]\d{9}))$/;;
  if (value == '' || value == undefined || value == null) {
    callback();
  } else {
    if ((!reg.test(value)) && value != '') {
      callback(new Error('请输入正确的电话号码或者固话号码'));
    } else {
      callback();
    }
  }
}
 
3、是否固话
export function validateTelphone(rule, value,callback) {
  const reg =/0\d{2,3}-\d{7,8}/;
  if(value==''||value==undefined||value==null){
    callback();
  }else {
    if ((!reg.test(value)) && value != '') {
      callback(new Error('请输入正确的固定电话)'));
    } else {
      callback();
    }
  }
}
 
4、是否手机号码
export function validatePhone(rule, value,callback) {
  const reg =/^[1][3-9][0-9]{9}$/;
  if(value==''||value==undefined||value==null){
    callback();
  }else {
    if ((!reg.test(value)) && value != '') {
      callback(new Error('请输入正确的电话号码'));
    } else {
      callback();
    }
  }
}
5、是否身份证号码
export function validateIdNo(rule, value,callback) {
  const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
  if(value==''||value==undefined||value==null){
    callback();
  }else {
    if ((!reg.test(value)) && value != '') {
      callback(new Error('请输入正确的身份证号码'));
    } else {
      callback();
    }
  }
}
 
6、是否邮箱
export function validateEMail(rule, value,callback) {
  const reg =/^([a-zA-Z0-9]+[-_\.]?)+@[a-zA-Z0-9]+\.[a-z]+$/;
  if(value==''||value==undefined||value==null){
    callback();
  }else{
    if (!reg.test(value)){
      callback(new Error('请输入正确的邮箱'));
    } else {
      callback();
    }
  }
}
 
7、合法url
export function validateURL(url) {
  const urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
  return urlregex.test(url);
}
 
8、验证内容是否包含英文数字以及下划线
export function isPassword(rule, value, callback) {
  const reg =/^[_a-zA-Z0-9]+$/;
  if(value==''||value==undefined||value==null){
    callback();
  } else {
    if (!reg.test(value)){
      callback(new Error('仅由英文字母,数字以及下划线组成'));
    } else {
      callback();
    }
  }
}
 
9、自动检验数值的范围
export function checkMax20000(rule, value, callback) {
  if (value == '' || value == undefined || value == null) {
    callback();
  } else if (!Number(value)) {
    callback(new Error('请输入[1,20000]之间的数字'));
  } else if (value < 1 || value > 20000) {
    callback(new Error('请输入[1,20000]之间的数字'));
  } else {
    callback();
  }
}
 
10、验证数字输入框最大数值
export function checkMaxVal(rule, value,callback) {
  if (value < 0 || value > 最大值) {
    callback(new Error('请输入[0,最大值]之间的数字'));
  } else {
    callback();
  }
}
 
11、验证是否1-99之间
export function isOneToNinetyNine(rule, value, callback) {
  if (!value) {
    return callback(new Error('输入不可以为空'));
  }
  setTimeout(() => {
    if (!Number(value)) {
      callback(new Error('请输入正整数'));
    } else {
      const re = /^[1-9][0-9]{0,1}$/;
      const rsCheck = re.test(value);
      if (!rsCheck) {
        callback(new Error('请输入正整数,值为【1,99】'));
      } else {
        callback();
      }
    }
  }, 0);
}
 
12、验证是否整数
export function isInteger(rule, value, callback) {
  if (!value) {
    return callback(new Error('输入不可以为空'));
  }
  setTimeout(() => {
    if (!Number(value)) {
      callback(new Error('请输入正整数'));
    } else {
      const re = /^[0-9]*[1-9][0-9]*$/;
      const rsCheck = re.test(value);
      if (!rsCheck) {
        callback(new Error('请输入正整数'));
      } else {
        callback();
      }
    }
  }, 0);
}
 
13、验证是否整数,非必填
export function isIntegerNotMust(rule, value, callback) {
  if (!value) {
    callback();
  }
  setTimeout(() => {
    if (!Number(value)) {
      callback(new Error('请输入正整数'));
    } else {
      const re = /^[0-9]*[1-9][0-9]*$/;
      const rsCheck = re.test(value);
      if (!rsCheck) {
        callback(new Error('请输入正整数'));
      } else {
        callback();
      }
    }
  }, 1000);
}
 
14、 验证是否是[0-1]的小数
export function isDecimal(rule, value, callback) {
  if (!value) {
    return callback(new Error('输入不可以为空'));
  }
  setTimeout(() => {
    if (!Number(value)) {
      callback(new Error('请输入[0,1]之间的数字'));
    } else {
      if (value < 0 || value > 1) {
        callback(new Error('请输入[0,1]之间的数字'));
      } else {
        callback();
      }
    }
  }, 100);
}
 
15、 验证是否是[1-10]的小数,即不可以等于0
export function isBtnOneToTen(rule, value, callback) {
  if (typeof value == 'undefined') {
    return callback(new Error('输入不可以为空'));
  }
  setTimeout(() => {
    if (!Number(value)) {
      callback(new Error('请输入正整数,值为[1,10]'));
    } else {
      if (!(value == '1' || value == '2' || value == '3' || value == '4' || value == '5' || value == '6' || value == '7' || value == '8' || value == '9' || value == '10')) {
        callback(new Error('请输入正整数,值为[1,10]'));
      } else {
        callback();
      }
    }
  }, 100);
}
 
16、验证是否是[1-100]的小数,即不可以等于0
export function isBtnOneToHundred(rule, value, callback) {
  if (!value) {
    return callback(new Error('输入不可以为空'));
  }
  setTimeout(() => {
    if (!Number(value)) {
      callback(new Error('请输入整数,值为[1,100]'));
    } else {
      if (value < 1 || value > 100) {
        callback(new Error('请输入整数,值为[1,100]'));
      } else {
        callback();
      }
    }
  }, 100);
}
 
17、验证是否是[0-100]的小数
export function isBtnZeroToHundred(rule, value, callback) {
  if (!value) {
    return callback(new Error('输入不可以为空'));
  }
  setTimeout(() => {
    if (!Number(value)) {
      callback(new Error('请输入[1,100]之间的数字'));
    } else {
      if (value < 0 || value > 100) {
        callback(new Error('请输入[1,100]之间的数字'));
      } else {
        callback();
      }
    }
  }, 100);
}
 
18、验证端口是否在[0,65535]之间
export function isPort(rule, value, callback) {
  if (!value) {
    return callback(new Error('输入不可以为空'));
  }
  setTimeout(() => {
    if (value == '' || typeof(value) == undefined) {
      callback(new Error('请输入端口值'));
    } else {
      const re = /^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/;
      const rsCheck = re.test(value);
      if (!rsCheck) {
        callback(new Error('请输入在[0-65535]之间的端口值'));
      } else {
        callback();
      }
    }
  }, 100);
}
 
19、验证端口是否在[0,65535]之间,非必填,isMust表示是否必填
export function isCheckPort(rule, value, callback) {
  if (!value) {
    callback();
  }
  setTimeout(() => {
    if (value == '' || typeof(value) == undefined) {
      //callback(new Error('请输入端口值'));
    } else {
      const re = /^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/;
      const rsCheck = re.test(value);
      if (!rsCheck) {
        callback(new Error('请输入在[0-65535]之间的端口值'));
      } else {
        callback();
      }
    }
  }, 100);
}
 
20、小写字母
export function validateLowerCase(val) {
  const reg = /^[a-z]+$/;
  return reg.test(val);
}
 
21、两位小数验证
const validateValidity = (rule, value, callback) => {
  if (!/(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(value)) {
    callback(new Error('最多两位小数!!!'));
  } else {
    callback();
  }
};
 
22、是否大写字母
export function validateUpperCase(val) {
  const reg = /^[A-Z]+$/;
  return reg.test(val);
}
 
23、是否大小写字母
export function validatAlphabets(val) {
  const reg = /^[A-Za-z]+$/;
  return reg.test(val);
}
 
24、密码校验
export const validatePsdReg = (rule, value, callback) => {
  if (!value) {
    return callback(new Error('请输入密码'))
  }
  if (!/^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$)([^\u4e00-\u9fa5\s]){6,20}$/.test(value)) {
    callback(new Error('请输入6-20位英文字母、数字或者符号(除空格),且字母、数字和标点符号至少包含两种'))
  } else {
    callback()
  }
}
 
25、中文校验
export const validateContacts = (rule, value, callback) => {
  if (!value) {
    return callback(new Error('请输入中文'))
  }
  if (!/^[\u0391-\uFFE5A-Za-z]+$/.test(value)) {
    callback(new Error('不可输入特殊字符'))
  } else {
    callback()
  }
}
 
26、身份证校验
export const ID = (rule, value, callback) => {
    if (!value) {
      return callback(new Error('身份证不能为空'))
    }
    if (! /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(value)) {
      callback(new Error('请输入正确的二代身份证号码'))
    } else {
      callback()
    }
}
 
27、账号校验
export const validateCode = (rule, value, callback) => {
  if (!value) {
    return callback(new Error('请输入账号'))
  }
  if (!/^(?![0-9]*$)(?![a-zA-Z]*$)[a-zA-Z0-9]{6,20}$/.test(value)) {
    callback(new Error('账号必须为6-20位字母和数字组合'))
  } else {
    callback()
  }
}
 
28、纯数字校验
export const validateNumber = (rule, value, callback) => {
    let numberReg = /^\d+$|^\d+[.]?\d+$/
    if (value !== '') {
        if (!numberReg.test(value)) {
            callback(new Error('请输入数字'))
        } else {
            callback()
        }
    } else {
        callback(new Error('请输入值'))
    }
}
 
29、最多一位小数
const onePoint = (rule, value, callback) => {
  if (!/^[0-9]+([.]{1}[0-9]{1})?$/.test(value)) {
    callback(new Error('最多一位小数!!!'));
  } else {
    callback();
  }
};
module.exports = {
    Username(rule, value, callback) {
        let reg = /^(?![0-9]*$)(?![a-zA-Z]*$)[a-zA-Z0-9]{6,12}$/
        matching(value, callback, reg, '请输入6-12位字母和数字组合')
    }, SimplePwd(rule, value, callback) {
        let reg = /^[_a-zA-Z0-9]+$/
        matching(value, callback, reg, '包含英文字母、数字及下划线组成')
    }, ComplexPwd(rule, value, callback) {
        let reg = /^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$)([^\u4e00-\u9fa5\s]){8,20}$/
        matching(value, callback, reg, '请输入8-20位英文字母、数字或者符号')
    }, Phone(rule, value, callback) {
        let reg = /^[1][3, 4, 5, 6, 7, 8][0-9]{9}$/
        matching(value, callback, reg, '请输入正确的手机')
    }, Email(rule, value, callback) {
        let reg = /^([a-zA-Z0-9]+[-_\.]?)+@[a-zA-Z0-9]+\.[a-z]+$/
        matching(value, callback, reg, '输入正确的邮箱')
    }, IdCard(rule, value, callback) { let reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/ 
       matching(value, callback, reg, '输入正确的身份证号码') }, Company(rule, value, callback) {
        let reg = /^[A-Z0-9]{8}-[A-Z0-9]$|^[A-Z0-9]{8}-[A-Z0-9]-[0-9]{2}$/
        matching(value, callback, reg, '请输入正确的营业执照')
    }, Weixin(rule, value, callback) {
        let reg = /^[a-zA-Z][a-zA-Z0-9_-]{5,19}$/
        matching(value, callback, reg, '请输入正确的微信号')
    }, Integer(rule, value, callback) {
        let reg = /^[1-9][0-9]*$/
        matching(value, callback, reg, '请输入正确的整数')
    }, Number(rule, value, callback) { let reg = /^\d+$|^\d+[.]?\d+$/  
          matching(value, callback, reg, '请输入纯数字') }, 
          Landline(rule, value, callback) { 
        let reg = /^(\d{3,4}-)?\d{7,8}$/   
         matching(value, callback, reg, '请输入正确的座机') 
     },
          Ip(rule, value, callback) {
               let reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/  
          matching(value, callback, reg, '请输入正确的IP')
     },
         Price(rule, value, callback) { let reg = /^-?\d{1,4}(?:\.\d{1,2})?$ /  
         matching(value, callback, reg, '请输入正确的价格') 
    }, 
         BankCard(rule, value, callback) { 
        let reg = /^([1-9]{1})(\d{14}|\d{18})$/   
         matching(value, callback, reg, '请输入正确的银行卡') }
}