前言
没有学习正则时,因为正则强大的功能,就以为学习正则的难度很大。但学习之后你会发现,你只需要花费几个小时就可以熟练的使用正则。在学习正则之前我们先看几个问题:1、什么是正则表达式?2、正则表达式的使用场景有哪些?3、正则表达式常用的方法有哪些?4、正则表达式常用的语法规则有哪些?,然后带着问题阅读本文。本文是将学习正则过程中所需要用到的站点和正则常用的语法规则进行总结和归纳,也希望可以帮助到需要学习正则的小伙伴们。
一、正则表达式的概念
定义: 正则表达式(Regular Expression)是用于描述一组字符串特征的模式,用来匹配特定的字符串。简单来说就是用来匹配特定的字符串的一种规则
二、正则表达式的使用场景
1、特定字符串判断是否符合正则规则
例如: 判断站点
https://juejin.cn/
✔、http://juejin.cn/
✖、https://juejin.com/
✖ 是否为掘金站点
let siteReg = /^https\:\/\/juejin.cn\//
let resultA = siteReg.test('https://juejin.cn/')
let resultB = siteReg.test('http://juejin.cn/')
let resultC = siteReg.test('https://juejin.com/')
// 三种不同格式的站点都可以匹配
console.log(resultA, resultB, resultC) // true false false
2、使用指定字符串替换正则匹配的字符串
例如: 把http://juejin.cn/
、https://juejin.com/
、https://juejin.cn/
三个站点中的juejin
替换成baidu
let resultA = 'https://juejin.cn/'.replace(siteReg, 'baidu')
let resultB = 'http://juejin.cn/'.replace(siteReg, 'baidu')
let resultC = 'https://juejin.com/'.replace(siteReg, 'baidu')
// -> https://baidu.cn/ http://baidu.cn/ https://baidu.com/
console.log(resultA, resultB, resultC)
三、可以使用正则表达式的方法
1、字符串方法使用正则
① search方法返回匹配到字符串的位置(返回数值)
let searchStr = 'hello world'
let result = searchStr.search(/o/g)
console.log(result) // -> 4
② 使用字符串上提取匹配项的方法.match()
返回值为匹配到的字符串的数组
let extractStr = "Extract the word 'coding' from this string."
let codingRegex = /coding/
let result = extractStr.match(codingRegex)
console.log(JSON.stringify(result)) // -> ["coding"]
③ 使用捕获组搜索和替换 -- .replace()
可以在字符串上使用 .replace()
方法来搜索并替换字符串中的文本。 .replace()
的输入首先是想要搜索的正则表达式匹配模式。 第二个参数是用于替换匹配的字符串或用于执行某些操作的函数。
let wrongText = 'The sky is silver.'
let silverRegex = /silver/
let result = wrongText.replace(silverRegex, 'blue')
console.log(result) // -> The sky is blue.
// 使用美元符号($)访问替换字符串中的捕获组。
let result1 = 'Code Camp'.replace(/(\w+)\s(\w+)/, '$2 $1')
console.log(result1) // -> Camp Code
2、正则上的方法使用
① 使用正则的测试方法.test()
**定义:**正则表达式使用test方法,验证字符是否符合正则表达式的校验条件,符合返回true
,不符合返回false
。
let testStr = "hello";
let testRegex = /hello/;
let result = testRegex.test(testStr);
console.log(result) // -> true
② 使用正则上提取匹配项的方法 .exec()
与match方法的不同之处,在全局匹配模式下,exec()方法每次只会匹配一个结果,但是每次匹配后会改变下次匹配的位置
var codingRegex = /coding/g
var codingStr =
'Extract the word "coding" from this string and get "coding".'
var resultA = codingRegex.exec(codingStr)
var resultB = codingRegex.exec(codingStr)
// ['coding', index: 18, input: 'Extract the word "coding" from this string and get "coding".', groups: undefined]
console.log(resultA)
// ['coding', index: 52, input: 'Extract the word "coding" from this string and get "coding".', groups: undefined]
console.log(resultB)
四、正则校验规则 -- 常用
1、匹配位置
元字符 | 描述 |
---|---|
^ | 匹配输入字行首 |
$ | 匹配输入行尾 |
2、字符集 []
元字符 | 描述 |
---|---|
[xyz] | 字符集合。匹配所包含的任意一个字符。 |
[^xyz] | 负值字符集合。匹配未包含的任意字符。 |
[a-z]、[0-9] | 字符范围。匹配指定范围内的任意字符。 |
[^a-z] 、[^0-9] | 负值字符范围。匹配任何不在指定范围内的任意字符。 |
3、量词
元字符 | 描述 |
---|---|
{n} | n是一个非负整数。匹配确定的n次。 |
{n,} | n是一个非负整数。至少匹配n次。 |
{n,m} | m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。 |
* | 匹配前面的子表达式任意次。 |
+ | 匹配前面的子表达式一次或多次(大于等于1次)。 |
? | 匹配前面的子表达式零次或一次。 |
*? | 重复任意次,但尽可能少重复 |
+? | 重复1次或更多次,但尽可能少重复 |
?? | 重复0次或1次,但尽可能少重复 |
{n,m}? | 重复n到m次,但尽可能少重复 |
4、常用字符集合
元字符 | 描述 |
---|---|
\d | 匹配一个数字字符。等价于[0-9]。 |
\D | 匹配一个非数字字符。等价于[^0-9] 。 |
\s | 匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。 |
\S | 匹配任何可见字符。等价于[^ \f\n\r\t\v] 。 |
\w | 匹配包括下划线的任何单词字符。类似但不等价于[A-Za-z0-9_] |
\W | 匹配任何非单词字符。等价于[^A-Za-z0-9_] 。 |
. | 除换行符以外的任意字符 |
5、空白字符
元字符 | 描述 |
---|---|
\f | 匹配一个换页符。 |
\n | 匹配一个换行符。 |
\r | 匹配一个回车符。 |
\t | 匹配一个制表符。 |
\v | 匹配一个垂直制表符。 |
6、修饰符
修饰符 | 描述 |
---|---|
i | 不区分(ignore)大小写 |
g | 全局(global)匹配 |
7、先行断言
元字符 | 描述 |
---|---|
A(?=assert) | 先行断言:查询assert之前的A |
A(?!assert) | 先行断言:查询不是assert之前的A |
8、分组匹配 ()
元字符 | 描述 |
---|---|
( ) | 将( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。 |
(pattern) | 匹配pattern并获取这一匹配。匹配的内容最多保存9个,可以通过\1 \2…\9来引用 |
(?:pattern) | 非获取匹配,匹配pattern但不获取匹配结果。 |
五、正则校验规则 -- 详解
1、正则表达式的基本规则 -- //
定义: 正则表达式(Regular Expression)是用于描述一组字符串特征的模式,用来匹配特定的字符串。
2、正则表达式的或 -- |
**定义:**匹配多个规则,这可以通过添加更多的匹配模式来实现。 这些匹配模式将包含更多的 OR
操作符来分隔它们,比如/yes|no|maybe/
。
let petString = "James has a pet cat.";
// 当匹配的字符串中包含dog|cat|bird|fish这几个字段时返回true
let petRegex = /dog|cat|bird|fish/;
let result = petRegex.test(petString);
console.log(result) // true
3、正则表达式匹配时忽略大小写 -- i
let myString = "freeCodeCamp";
let fccRegex = /freecodecamp/i;
let result = fccRegex.test(myString);
console.log(result) // true
4、正则表达式全局匹配 -- g
let twinkleStar = "Twinkle, twinkle, little star";
let starRegex = /twinkle/gi;
let result = twinkleStar.match(starRegex);
console.log(JSON.stringify(result)) // -> ["Twinkle","twinkle"]
5、匹配所有字符 -- .
let exampleStr = "Let's have fun with regular expressions!"
let unRegex = /.un/
let result = exampleStr.match(unRegex)
console.log(JSON.stringify(result)) // -> ["fun"]
6、匹配指定的多个字符 -- []
let quoteSample = 'Beware of bugs in the above code; I have only proved it correct, not tried it.'
let vowelRegex = /[aeiou]/gi
let result = quoteSample.match(vowelRegex)
console.log(JSON.stringify(result))
1、匹配字母表中的字母 -- [a-e]
let quoteSample = 'The quick brown fox jumps over the lazy dog.'
let alphabetRegex = /[a-z]/gi
let result = quoteSample.match(alphabetRegex)
console.log(JSON.stringify(result))
2、匹配0到9的数字 -- [0-9]
let jennyStr = '8675309'
let myRegex = /[0-9]/gi
let result = jennyStr.match(myRegex)
console.log(JSON.stringify(result)) // -> ["8","6","7","5","3","0","9"]
7、匹配单个未指定的字符 -- ^
要创建否定字符集,需要在开始括号后面和不想匹配的字符前面放置脱字符(即^
)。符 .
、!
、[
、@
、/
和空白字符等也会被匹配。
let quoteSample = "3 blind mice.";
let myRegex = /[^aeiou0-9]/gi;
let result = quoteSample.match(myRegex);
[" ","b","l","n","d"," ","m","c","."]
8、匹配出现一次或连续多次的字符 -- +
let difficultSpelling = 'Mississippi'
let myRegex = /s+/g // 修改这一行
let result = difficultSpelling.match(myRegex)
console.log(JSON.stringify(result)) // -> ["ss","ssssssssss"]
9、匹配出现零次或多次的字符 -- *
let soccerWord = "gooooooooal!";
let gPhrase = "gut feeling";
let oPhrase = "over the moon";
let goRegex = /go*/;
soccerWord.match(goRegex); // -> ["goooooooo"]
gPhrase.match(goRegex); // -> ["g"]
oPhrase.match(goRegex); // -> null
10、惰性匹配,需要配合+
或*
使用 -- ?
在正则表达式中,贪婪(greedy)匹配会匹配到符合正则表达式匹配模式的字符串的最长可能部分,并将其作为匹配项返回,也是正则匹配的默认原则。 另一种方案称为懒惰(lazy)匹配,它会匹配到满足正则表达式的字符串的最小可能部分。使用 ?
字符来将其变成懒惰匹配。
let text = 'tlitanic'
let myRegex = /t[a-z]*i/
let myRegex1 = /t[a-z]*?i/
let result = text.match(myRegex)
let result1 = text.match(myRegex1)
console.log(JSON.stringify(result)) // -> ["tlitani"]
console.log(JSON.stringify(result1)) // -> ["tli"]
11、匹配有或者无字符 -- ?
匹配模式可能有不确定是否存在的部分,就可以使用?
匹配
let american = "color";
let british = "colour";
let rainbowRegex= /colou?r/;
// 字符传中的u具有不确定性,无论有还是没有都会匹配成功
rainbowRegex.test(american); // true
rainbowRegex.test(british); // true
12、匹配字符串的开头 -- ^
let rickyAndCal = 'Cal and Ricky both like racing.'
let calRegex = /^Cal/ // 修改这一行
let result = calRegex.test(rickyAndCal)
console.log(result) // -> true
13、匹配字符串的末尾 -- $
let caboose = "The last car on a train is the caboose";
let lastRegex = /caboose$/; // 修改这一行
let result = lastRegex.test(caboose);
console.log(result) // -> true
当 ^ 和 之间的内容
let specialSymbol = /^code$/
let result = specialSymbol.test('code')
console.log(result) // -> true
14、匹配所有的字母、数字以及下划线 \w
JavaScript 中与字母表匹配的最接近的元字符是\w
。 这个缩写等同于[A-Za-z0-9_]
。 此字符类匹配大写字母和小写字母以及数字。 注意,这个字符类也包含下划线字符 (_
)。
let quoteSample = 'The five'
let alphabetRegexV2 = /\w/g // 修改这一行
let result = quoteSample.match(alphabetRegexV2)
console.log(JSON.stringify(result))
// -> ['T', 'h', 'e', 'f', 'i', 'v', 'e']
15、匹配除了字母和数字的所有符号\W
\W
搜寻和 \w
相反的匹配模式。 注意,相反匹配模式使用大写字母。 此缩写与 [^A-Za-z0-9_]
是一样的。
let shortHand = /\W/;
let numbers = "42%";
let sentence = "Coding!";
numbers.match(shortHand); // -> ['%']
sentence.match(shortHand); // -> ['!']
16、匹配所有数字 -- \d
查找数字字符的缩写是 \d
,注意是小写的 d
。 这等同于元字符 [0-9]
,它查找 0 到 9 之间任意数字的单个字符。
let movieName = '2001: A Space Odyssey'
let numRegex = /\d/g // 修改这一行
let result = movieName.match(numRegex)
console.log(result) // -> ['2', '0', '0', '1']
17、匹配所有非数字 -- \D
查找非数字字符的缩写是 \D
。 这等同于字符串 [^0-9]
,它查找不是 0 - 9 之间数字的单个字符。
let movieName = '2001: A Space Odyssey'
let noNumRegex = /\D/g // 修改这一行
let result = movieName.match(noNumRegex)
console.log(result)
// -> [':', ' ', 'A', ' ', 'S', 'p', 'a', 'c', 'e', ' ', 'O', 'd', 'y', 's', 's', 'e', 'y']
18、匹配空白字符 -- \s
可以使用 \s
搜寻空格,其中 s
是小写。
let sample = 'Whitespace is important in separating words'
let countWhiteSpace = /\s/g // 修改这一行
let result = sample.match(countWhiteSpace)
console.log(JSON.stringify(result)) // -> [" "," "," "," "," "]
19、匹配非空白字符 -- \S
使用 \S
搜寻非空白字符,其中 s
是大写。 此匹配模式将不匹配空格、回车符、制表符、换页符和换行符。
let sample = 'Whitespace is'
let countWhiteSpace = /\S/g // 修改这一行
let result = sample.match(countWhiteSpace)
console.log(JSON.stringify(result)) // -> ["W","h","i","t","e","s","p","a","c","e","i","s"]
20、转义字符 -- 关键字\
// 匹配 /
let specialSymbol = /^\//
let result = specialSymbol.test('/specialSymbol')
console.log(result) // -> true
21、匹配混合字符组 -- ()
et testStr = "Pumpkin";
let testRegex = /P(engu|umpk)in/;
testRegex.test('Pumpkin'); // true
testRegex.test('Penguin'); // true
22、指定匹配的上限和下限 -- {}
数量说明符(quantity specifiers)指定匹配模式的上下限。 数量说明符与花括号({
和 }
)一起使用。 可以在花括号之间放两个数字,这两个数字代表匹配模式的上限和下限。
let multipleA = /a{3,5}h/;
multipleA.test("aaaaah"); // -> true
multipleA.test("aaah"); // -> true
multipleA.test("aah"); // -> false
let multipleB = /a{3,}h/; // 只指定匹配的下限
multipleB.test("aaaaah"); // -> true
multipleB.test("aaah"); // -> true
multipleBtest("aah"); // -> false
let multipleC = /a{3}h/; // 只指定匹配的确切数字
multipleC.test("aaaaah"); // -> false
multipleC.test("aaah"); // -> true
multipleC.test("aah"); // -> false
23、正向先行断言和负向先行断言 -- (?=...)
和(?!...)
正向先行断言会查看并确保搜索匹配模式中的元素存在,但实际上并不匹配。 正向先行断言的用法是 (?=...)
,其中 ...
就是需要存在但不会被匹配的部分。
另一方面,负向先行断言会查看并确保搜索匹配模式中的元素不存在。 负向先行断言的用法是 (?!...)
,其中 ...
是希望不存在的匹配模式。 如果负向先行断言部分不存在,将返回匹配模式的其余部分。
let quit = "qu";
let noquit = "qt";
let quRegex= /q(?=u)/;
let qRegex = /q(?!u)/;
quit.match(quRegex); // -> ["q"]
noquit.match(qRegex); // -> ["q"]
24、使用捕获组重用模式 -- \1
正则表达式可以通过( )分为多个组,每个组独立匹配若干字符,分组匹配的子字符串被保存到一个临时的“变量”, 可以使用同一正则表达式和反斜线及捕获组的编号来访问它(例如:\1
)。 捕获组按其开头括号的位置自动编号(从左到右),从 1 开始,最多9个。
let repeatNum = "42 42 42";
// /^(\d{2,3})\s\1\s\1$/ == /^(\d{2,3})\s\(\d{2,3})\s\(\d{2,3})$/
let reRegex = /^(\d{2,3})\s\1\s\1$/; // (\d{2,3})这个规则就是编号为1的变量
let result = reRegex.test(repeatNum);
console.log(result) // -> true