JavaScript正则表达式使用及常用示例
# 正则表达式
正则表达式是用于匹配字符串中字符组合的模式。正则表达式的强大与灵活不必多说,在 JavaScript中,正则表达式也是对象。这些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、matchAll、replace、search 和 split 方法。
# 创建正则
js中可以使用以下两种方法构建一个正则表达式:
使用一个正则表达式字面量,其由包含在斜杠之间的模式组成,如下所示:
const regExp = /ab+c/;
脚本加载后,正则表达式字面量就会被编译。当正则表达式保持不变时,使用此方法可获得更好的性能。
调用RegExp对象的构造函数,如下所示:
const regExp = new RegExp("ab+c");
在脚本运行过程中,用构造函数创建的正则表达式会被编译。如果正则表达式将会改变,或者它将会从用户输入等来源中动态地产生,就需要使用构造函数来创建正则表达式。
JavaScript的正则表达式还有几个特殊的标志,最常用的是g,表示全局匹配:
const r1 = /test/g;
// 等价于:
const r2 = new RegExp('test', 'g');
除此之外还有gmiyus
标示 | 缩写 | 说明 |
---|---|---|
g | global | 全局匹配,匹配到第一个之后继续搜索全部 |
i | insensitive | 忽略大小写 |
m | multiple line | 多行模式 |
s | single line | 单行模式 |
u | unicode | 开启完整的 unicode 支持 |
y | sticky | 粘滞模式 |
这个示例^[\u4E00-\u9FA5A-Za-z0-9_]+$
含义为匹配中文、英文、数字包括下划线
// 字面量形式可直接··//···包裹起来
const reg = /^[\u4E00-\u9FA5A-Za-z0-9_]+$/
// new 对象的时候,因为字符串的转义问题,字符串的两个\\实际上是一个\
const reg2 = new RegExp('^[\\u4E00-\\u9FA5A-Za-z0-9_]+$')
# 正则方法
# test
test方法用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false。
/^hello/.test('hello'); // true 以hello开头
/123hello/.test('hello'); // true 包含hello
/h1ello/.test('hello'); // false
注意
如果正则表达式设置了全局标志,test() 的执行会改变正则表达式,lastIndex属性。连续的执行test()方法,后续的执行将会从 lastIndex 处开始匹配字符串,(exec() 同样改变正则本身的 lastIndex属性值).
let reg = /hello/g;
// lastIndex = 0
reg.lastIndex === 0 // true
reg.test('hello'); // true
// lastIndex = 5
reg.lastIndex === 5 // true
reg.test('hello'); // false
# match
一个在字符串中执行查找匹配的String方法,它返回一个数组,在未匹配到时会返回 null。
'1,23,4akd,121'.match(/\d+/g); // ["1", "23", "4", "121"] 全局模式下会匹配出所有满足的元素
'1,23,4akd,121'.match(/\d+/); // ["1", index: 0, input: "1,23,4akd,121", groups: undefined]
# matchAll
一个在字符串中执行查找所有匹配的String方法,它返回一个迭代器(iterator)。
let it = '1,23,4akd,121'.matchAll(/\d+/g);
it.next(); // {value: ["1", index: 0, input: "1,23,4akd,121", groups: undefined], done: false}
it.next(); // {value: ["23", index: 2, input: "1,23,4akd,121", groups: undefined], done: false}
# replace
一个在字符串中执行查找匹配的String方法,并且使用替换字符串替换掉匹配到的子字符串。
"Mr Blue has a blue house and a blue car".replace('b','121'); // "Mr Blue has a 121lue house and a blue car"
"Mr Blue has a blue house and a blue car".replace(/b/g,'121'); // "Mr Blue has a 121lue house and a 121lue car"
"Mr Blue has a blue house and a blue car".replace(/b/gi,'121'); // "Mr 121lue has a 121lue house and a 121lue car"
# search
一个在字符串中测试匹配的String方法,它返回匹配到的位置索引,或者在失败时返回-1。
"Mr. Blue has a blue house".search('Mr'); // 0
"Mr. Blue has a blue house".search('mr'); // -1
"Mr. Blue has a blue house".search(/mr/i); // 0
# split
一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的 String 方法。
"How are you doing today?".split(''); // ["H", "o", "w", " ", "a", "r", "e", " ", "y", "o", "u", " ", "d", "o", "i", "n", "g", " ", "t", "o", "d", "a", "y", "?"]
"How are you doing today?".split(); // ["How are you doing today?"]
"How are you doing today?".split(' '); // ["How", "are", "you", "doing", "today?"]
"How are you doing today?".split('o'); // ["H", "w are y", "u d", "ing t", "day?"]
"How are you doing today?".split(' ',3); // ["How", "are", "you"]
"Ho1w are you d1oing t3oday?".split(/\d/) // ["Ho", "w are you d", "oing t", "oday?"]
# exec
一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(未匹配到则返回 null)。
注意
在设置了 global 或 sticky 标志位的情况下(如 /foo/g or /foo/y),JavaScript RegExp 对象是有状态的。他们会将上次成功匹配后的位置记录在 lastIndex 属性中。使用此特性,exec() 可用来对单个字符串中的多次匹配结果进行逐条的遍历(包括捕获到的匹配),而相比之下, String.prototype.match() 只会返回匹配到的结果。
如果你只是为了判断是否匹配(true或 false),可以使用 RegExp.test() 方法,或者 String.search() 方法。
const reg = /a/g;
const str = 'abc_abc_abc'
const r1 = reg.exec(str);
r1 // ["a"]
r1.index // 0
reg.lastIndex // 1
const r2 = reg.exec(str);
r2 // ["a"]
r2.index // 4
reg.lastIndex // 5
const r3 = reg.exec(str);
r3 // ["a"]
r3.index // 8
reg.lastIndex // 9
const r4 = reg.exec(str);
r4 // null
reg.lastIndex // 0
const reg = /a/g;
const str = 'abc_abc_abc'
while(true) {
let match = reg.exec(str);
if (!match) break;
console.log('#' + match.index + ':' + match[0]);
}
// #0:a
// #4:a
// #8:a
# 常用正则表达式
# 数字
/^\d+$/.test(123); // 正整数
/^-\d+$/.test(-123); // 负整数
/^-?\d+$/.test(-123); // 正负整数
/^\d*\.?\d+$/.test(123.2); // 小数正数
/^-\d*\.?\d+$/.test(-123.1); // 小数负数
/^-?\d*\.?\d+$/.test(-12.12); // 正负小数
/^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$/.test(123.12);// 非负浮点数
/^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$/.test(123.12);// 非正浮点数
/^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/.test('123@123.com') // true
# Url
/^((https?|ftp|file):\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/.test('https://www.nowhere.ink/') // true
# 十六进制颜色正则
/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/.test('#f8f8f8')
# 中文正则
/[\u4E00-\u9FA5]/.test('速度快'); // true 包含中文
/^[\u4e00-\u9fa5]{0,}$/.test('sk说看看'); // false 全部中文
# 字母
/^[A-Z]+$/.test('AA'); // 大写字母
/^[a-z]+$/.test('AA'); // 小写字母
/^[A-Za-z0-9]+$/.test('A1aA'); // 大小写字母数字
# 其他
/^.{3,20}$/.test('1233'); // 长度为3-20的所有字符