# 正则表达式
- \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
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个数字划分的位置,直到结束位置
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
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
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]
2
3
4
5
# 实例方法及属性
var reg = /([^=&?]+)=([^=&?]+)+/gim
var str = 'https://mbd.baidu.com?names=cao&age=100&sex=男'
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
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)
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
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 = {
'<': '<',
'>': '>',
'"': '"',
'&': '&',
' ': '\n',
'	': '\t',
''': "'"
};
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/);
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}
# 参考文章
# (?=p) (?!p)(?<=p) (?<!p>)总结
(?=xx)
后面紧跟xx的位置
'q_xxx_love_sxxtudy_1.mp4'.replace(/(?=xx)/g,"❤️");
'q_❤️x❤️xx_love_s❤️xxtudy_1.mp4'
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❤️'
2
3
(?<=xx)
前面紧跟xx的位置
'q_xxx_love_sxxtudy_1.mp4'.replace(/(?<=xx)/g,"❤️");
'q_xx❤️x❤️_love_sxx❤️tudy_1.mp4'
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❤️'
2
3
# 推荐好文
# 注意⚠️⚠️⚠️
- /[-+*/]/.test('324-34')
- /[+-*/]/,这里的-放在了中间,表示了加号到星号的范围,所以会报错,类似 [a-zA-Z]
- 匹配数组 var str = '111 [1,2,3]==='; str.match(/[[\d+,?]+]/)