# 正则表达式

  • \w 单词字符-包括 [a-zA-Z0-9_]
  • \W 非单词字符-[^a-zA-Z0-9_]
  • \b (opens new window) 匹配一个词的边界
  • \B (opens new window) 匹配一个非单词边界
  • \d 数字
  • \D 非数字
  • \n 换行符
  • \r 回车符
  • \s 空白字符 - 包括空格、制表符、换页符和换行符
  • \S 匹配一个非空白字符

# 难点匹配

# 分组捕获


var re = /(?:\d{3}|\(\d{3}\))([-\/\.])\d{3}\1\d{4}/;

var str = 012-123-1233
var str1 = (012)/123/1234
var str2 = (012).123.1234
1
2
3
4
5
6

# 先行断言

var reg = /java(?=script)/g 匹配后面紧跟script的【java】

var reg= /java(?=script)/g
var str = 'javaEE'
var str1 = 'javascript'
reg.exec(str) // null
reg.exec(str1) // ["java", index: 0, input: "javascript", groups: undefined]

'a123456a78911111'.replace(/(?=(\B\d{4})+)/g,'-')
找后面跟4个数字的位置,只要后面跟4个数字的位置就行,不用匹配到最后


'a123456a78911111'.replace(/(?=(\B\d{4})+$)/g,'-')

加了$表示,从当前位置开始找到能把字符串按4个数字划分的位置,直到结束位置
1
2
3
4
5
6
7
8
9
10
11
12
13

# 正向否定查找

var reg = /java(?!scirpt)/g 匹配后面不跟scirpt的【java】

var reg= /java(?!script)/g
var str = 'javaEE'
var str1 = 'javascript'
reg.exec(str) // ["java", index: 0, input: "javaEE", groups: undefined]
reg.exec(str1) // null
1
2
3
4
5

# 后行断言

var reg = /(?<=Tom|Jerry)动画片/g 匹配前面紧跟Tom或者Jerry的【动画片】

var reg= /(?<=Tom|Jerry)动画片/g
var str = 'Tom动画片'
var str1 = '其他动画片'
reg.exec(str) // ["动画片", index: 3, input: "Tom动画片", groups: undefined]
reg.exec(str1) // null
1
2
3
4
5

# 反向否定查找

var reg = /(?<!Tom|Jerry)动画片/g 匹配前面没有紧挨Tom或者Jerry的【动画片】

var reg= /(?<!Tom|Jerry)动画片/g
var str = 'Tom动画片'
var str1 = '其他动画片'
reg.exec(str) // null
reg.exec(str1) // ["动画片", index: 2, input: "其他动画片", groups: undefined]
1
2
3
4
5

# 实例方法及属性

var reg = /([^=&?]+)=([^=&?]+)+/gim
var str = 'https://mbd.baidu.com?names=cao&age=100&sex=男'
1
2
属性 类型 含义
flags string gim 含有 RegExp 对象 flags 的字符串
global boolean true 针对字符串中所有可能的匹配项测试正则表达式,还是仅针对第一个匹配项。
ignoreCase boolean true 匹配文本的时候是否忽略大小写。
multiline boolean true 是否进行多行搜索。
source string ([^=&?])=([^=&?]) 正则表达式的文本
sticky boolean false
unicode boolean false Unicode 功能是否开启
toString function /https://mbd.baidu.com?name=cao&age=100&sex=男/
exec function ["e=c", "e", "c", index: 25, input: "https://mbd.baidu.com?name=cao&age=100&sex=男", groups: undefined]
test function true 该正则在字符串里是否有匹配。

# 方法详解

exec() 方法在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null。

在设置了 global 或 sticky 标志位的情况下(如 /foo/g or /foo/y),JavaScript RegExp 对象是有状态的。他们会将上次成功匹配后的位置记录在 lastIndex 属性中。使用此特性,exec() 可用来对单个字符串中的多次匹配结果进行逐条的遍历(包括捕获到的匹配),而相比之下, String.prototype.match() 只会返回匹配到的结果。

var reg = /([^=&?]+)=([^=&?]+)+/gim
var str = 'https://mbd.baidu.com?names=cao&age=100&sex=男'

reg.exec(str) // ["names=cao", "names", "cao", index: 22, input: "https://mbd.baidu.com?names=cao&age=100&sex=男", groups: undefined]
reg.exec(str) // ["age=100", "age", "100", index: 32, input: "https://mbd.baidu.com?names=cao&age=100&sex=男", groups: undefined]
reg.exec(str) // ["sex=男", "sex", "男", index: 40, input: "https://mbd.baidu.com?names=cao&age=100&sex=男", groups: undefined]
reg.exec(str) // null
1
2
3
4
5
6
7

用exec方法解析url

var str = 'https://mbd.baidu.com?names=cao&age=100&sex=男&sex=女'
function parseUrl(str) {
    var obj = {}
    var reg = /([^&=?]+)=([^&=?]+)/g
    while(true) {
        var result = reg.exec(str)
        if(result === null) return obj
        const key = result[1]
        const value = result[2]
        obj[key] ? (obj[key].push(value)): (obj[key] = [value])
    }
}
parseUrl(str)

1
2
3
4
5
6
7
8
9
10
11
12
13
14

test() 方法执行一个检索,用来查看正则表达式与指定的字符串是否匹配。返回 true 或 false。

var reg = /([^=&?]+)=([^=&?]+)+/gim
var str = 'https://mbd.baidu.com?names=cao&age=100&sex=男'
reg.test(str) // true
1
2
3

# 字符串可以匹配正则的方法

  • split
  • match
  • matchAll, 正则必须带g
  • replace,替换掉匹配到的字符
  • replaceAll
  • search, 返回首次匹配项的索引

# 正则练习

Vue里的正则

DETAILS

  var camelizeRE = /-(\w)/g;
  var camelize = cached(function (str) {
    return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; })
  });

  var hyphenateRE = /\B([A-Z])/g;
  var hyphenate = cached(function (str) {
    return str.replace(hyphenateRE, '-$1').toLowerCase()
  });

  var unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/;
  var isIE = UA && /msie|trident/.test(UA);
  var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');
  var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
  var isPhantomJS = UA && /phantomjs/.test(UA);
  var isFF = UA && UA.match(/firefox\/(\d+)/);
  var classifyRE = /(?:^|[-_])(\w)/g;
  var match = file.match(/([^/\\]+)\.vue$/);
  var simpleCheckRE = /^(String|Number|Boolean|Function|Symbol)$/;
  var match = fn && fn.toString().match(/^\s*function (\w+)/);
  var validDivisionCharRE = /[\w).+\-_$\]]/;
  var listDelimiter = /;(?![^(]*\))/g;
  var propertyDelimiter = /:(.+)/; 
  var cssVarRE = /^--/;
  var importantRE = /\s*!important$/;
  var whitespaceRE = /\s+/;
  var transformRE = /\b(transform|all)(,|$)/;
  var defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g;
  var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g;
  var attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/;
  var dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/;
  var ncname = "[a-zA-Z_][\\-\\.0-9_a-zA-Z" + (unicodeRegExp.source) + "]*";
  var qnameCapture = "((?:" + ncname + "\\:)?" + ncname + ")";
  var startTagOpen = new RegExp(("^<" + qnameCapture));
  var startTagClose = /^\s*(\/?)>/;
  var endTag = new RegExp(("^<\\/" + qnameCapture + "[^>]*>"));
  var doctype = /^<!DOCTYPE [^>]+>/i;
  // #7298: escape - to avoid being passed as HTML comment when inlined in page
  var comment = /^<!\--/;
  var conditionalComment = /^<!\[/;
  var decodingMap = {
    '&lt;': '<',
    '&gt;': '>',
    '&quot;': '"',
    '&amp;': '&',
    '&#10;': '\n',
    '&#9;': '\t',
    '&#39;': "'"
  };
  var encodedAttr = /&(?:lt|gt|quot|amp|#39);/g;
  var encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#39|#10|#9);/g;
  var onRE = /^@|^v-on:/;
  var dirRE = /^v-|^@|^:|^#/;
  var forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
  var forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
  var stripParensRE = /^\(|\)$/g;
  var dynamicArgRE = /^\[.*\]$/;
  var argRE = /:(.*)$/;
  var bindRE = /^:|^\.|^v-bind:/;
  var modifierRE = /\.[^.\]]+(?=[^\]]*$)/g;

  var slotRE = /^v-slot(:|$)|^#/;

  var lineBreakRE = /[\r\n]/;
  var whitespaceRE$1 = /\s+/g;

  var invalidAttributeRE = /[\s"'<>\/=]/;

  var ieNSBug = /^xmlns:NS\d+/;
  var ieNSPrefix = /^NS\d+:/;
  var fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function(?:\s+[\w$]+)?\s*\(/;
  var fnInvokeRE = /\([^)]*?\);*$/;
  var simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/;
  var prohibitedKeywordRE = new RegExp('\\b' + (
    'do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' +
    'super,throw,while,yield,delete,export,import,return,switch,default,' +
    'extends,finally,continue,// debugger,function,arguments'
  ).split(',').join('\\b|\\b') + '\\b');
  // these unary operators should not be used as property/method names
  var unaryOperatorsRE = new RegExp('\\b' + (
    'delete,typeof,void'
  ).split(',').join('\\s*\\([^\\)]*\\)|\\b') + '\\s*\\([^\\)]*\\)');

  // strip strings in expressions
  var stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g;
  var lines = source.split(/\r?\n/);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

# 常用正则

  • 数字:^[0-9]*$

  • n位的数字:^\d{n}$

  • 至少n位的数字:^\d{n,}$

  • m-n位的数字:^\d{m,n}$

  • 零和非零开头的数字:^(0|[1-9][0-9]*)$

  • 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$

  • 带1-2位小数的正数或负数:^(-)?\d+(.\d{1,2})$

  • 正数、负数、和小数:^(-|+)?\d+(.\d+)?$

  • 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$

  • 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$

  • 非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]){1,3}$ 或 ^+?[1-9][0-9]$

  • 非零的负整数:^-[1-9][]0-9"$ 或 ^-[1-9]\d$

  • 非负整数:^\d+$ 或 ^[1-9]\d*|0$

  • 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$

  • 非负浮点数:^\d+(.\d+)?$ 或 ^[1-9]\d*.\d*|0.\d*[1-9]\d*|0?.0+|0$

  • 非正浮点数:^((-\d+(.\d+)?)|(0+(.0+)?))$ 或 ^(-([1-9]\d*.\d*|0.\d*[1-9]\d*))|0?.0+|0$

  • 正浮点数:^[1-9]\d*.\d*|0.\d*[1-9]\d*$ 或 ^(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9]))$

  • 负浮点数:^-([1-9]\d*.\d*|0.\d*[1-9]\d*)$ 或 ^(-(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9])))$

  • 浮点数:^(-?\d+)(.\d+)?$ 或 ^-?([1-9]\d*.\d*|0.\d*[1-9]\d*|0?.0+|0)$

  • 汉字:^[\u4e00-\u9fa5]{0,}$

  • 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$

  • 长度为3-20的所有字符:^.{3,20}$

  • 由26个英文字母组成的字符串:^[A-Za-z]+$

  • 由26个大写英文字母组成的字符串:^[A-Z]+$

  • 由26个小写英文字母组成的字符串:^[a-z]+$

  • 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$

  • 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$

  • 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$

  • 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+- $ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$

  • 可以输入含有^%&',;=?$"等字符:[^%&',;=?$\x22]+

  • 禁止输入含有~的字符:[^~\x22]+

  • Email地址:^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$

  • 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+.?

  • InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+.)+[\w-]+(/[\w-./?%&=]*)?$

  • 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|4|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$

  • 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^((\d{3,4}-)|\d{3.4}-)?\d{7,8}$

  • 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}

  • 电话号码正则表达式(支持手机号码,3-4位区号,7-8位直播号码,1-4位分机号): ((\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$)

  • 身份证号(15位、18位数字),最后一位是校验位,可能为数字或字符X:(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)

  • 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$

  • 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$

  • 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在 8-10 之间):^(?=.\d)(?=.[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,10}$

  • 强密码(必须包含大小写字母和数字的组合,可以使用特殊字符,长度在8-10之间):^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}$

  • 日期格式:^\d{4}-\d{1,2}-\d{1,2}

  • 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$

  • 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$

  • 钱的输入格式:有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$

  • 钱的输入格式:这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$

  • 钱的输入格式:一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$

  • 钱的输入格式:这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧。下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$

  • 钱的输入格式:必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$

  • 钱的输入格式:这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$

  • 钱的输入格式:这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$

  • 钱的输入格式:1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$

  • 钱的输入格式:备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里

  • xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\.[x|X][m|M][l|L]$

  • 中文字符的正则表达式:[\u4e00-\u9fa5]

  • 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))

  • 空白行的正则表达式:\n\s*\r (可以用来删除空白行)

  • HTML标记的正则表达式:<(\S*?)[^>]>.?|<.? /> ( 首尾空白字符的正则表达式:^\s|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)

  • 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)

  • 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)

  • IPv4地址:((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}

# 参考文章

  1. 正则表达式 (opens new window)

# (?=p) (?!p)(?<=p) (?<!p>)总结

(?=xx) 后面紧跟xx的位置

'q_xxx_love_sxxtudy_1.mp4'.replace(/(?=xx)/g,"❤️");

'q_❤️x❤️xx_love_s❤️xxtudy_1.mp4'
1
2
3

(?!xx)后面不跟xx的位置

'q_xxx_love_sxxtudy_1.mp4'.replace(/(?!xx)/g,"❤️");

'❤️q❤️_xx❤️x❤️_❤️l❤️o❤️v❤️e❤️_❤️sx❤️x❤️t❤️u❤️d❤️y❤️_❤️1❤️.❤️m❤️p❤️4❤️'
1
2
3

(?<=xx)前面紧跟xx的位置

'q_xxx_love_sxxtudy_1.mp4'.replace(/(?<=xx)/g,"❤️");

'q_xx❤️x❤️_love_sxx❤️tudy_1.mp4'
1
2
3

(?<!xx)前面不跟xx的位置

'q_xxx_love_sxxtudy_1.mp4'.replace(/(?<!xx)/g,"❤️");

'❤️q❤️_❤️x❤️xx_❤️l❤️o❤️v❤️e❤️_❤️s❤️x❤️xt❤️u❤️d❤️y❤️_❤️1❤️.❤️m❤️p❤️4❤️'
1
2
3

# 推荐好文

# 注意⚠️⚠️⚠️

  1. /[-+*/]/.test('324-34')
  2. /[+-*/]/,这里的-放在了中间,表示了加号到星号的范围,所以会报错,类似 [a-zA-Z]
  3. 匹配数组 var str = '111 [1,2,3]==='; str.match(/[[\d+,?]+]/)