正则表达式
描述了一种字符串匹配的模式
可以用来检查一个串是否含有某种子串
将匹配的子串替换或者从某个串中取出符合某个条件的子串等。
-------------------------------------------------------------------------------------------
- 文字匹配模式(精确匹配)
正则表达式/literal/,通过放在测试方法.test括号内使用.
- 使用测试方法
测试正则表达式的一种方法是使用 .test() 方法。
.test() 方法会把编写的正则表达式和字符串(即括号内的内容)匹配,如果成功匹配到字符则返回 true,反之,返回 false。
let testStr = "freeCodeCamp"; let testRegex = /Code/; testRegex.test(testStr);
//此处检测到testStr含有目标字段testRegex,test方法会返回true
- 同时用多种模式匹配文字字符串
|标签
或操作符如/yes|no/,匹配到其一为true
- 匹配时选择忽略大小写
i标签
忽略大小写的标志,/ignorecase/i加在正则表达式之后使用
- 提取匹配项
通过使用 .match() 方法来提取找到的实际匹配项。
还可以使用字符串来调用 .match() 方法
并在括号内使用正则表达式。
"Hello, World!".match(/Hello/);let ourStr = "Regular expressions";let ourRegex = /expressions/;ourStr.match(ourRegex);
/*这里第一个 match 将返回 ["Hello"] 第二个将返回 ["expressions"]。*/
请注意, .match 语法是目前为止一直使用的 .test 方法中的“反向”:
'string'.match(/regex/);/regex/.test('string');
- 全局匹配
通过使用g标签来实现全局匹配
let repeatRegex = /Repeat/g;//g为全局匹配标签testStr.match(repeatRegex);
这里 match 返回值 ["Repeat", "Repeat", "Repeat"]
注意:在正则表达式上可以有多个标志,比如 /search/gi
- 用通配符匹配任何内容(匹配所有)
通配符.允许有误差的匹配
例如,如果想匹配 hug、huh、hut 和 hum,可以使用正则表达式 /hu./ 匹配以上四个单词。
let humStr = "I'll hum a song";let hugStr = "Bear hug";let huRegex = /hu./;//通配符.huRegex.test(humStr);huRegex.test(hugStr);//都会返回true
- 字符集[](介于精确与所有之间的平衡选项)
[]标签,在//正则表达式中使用
正则表达式的文字匹配模式(/literal/)和通配符模式(/.moshi/)。
这是正则表达式的两种极端情况,一种是精确匹配,而另一种则是匹配所有。
在这两种极端情况之间有一个平衡选项就是字符集匹配。
例如,如果想要匹配 bag、big 和 bug,但是不想匹配 bog。 可以创建正则表达式 /b[aiu]g/ 来执行此操作。 [aiu] 是只匹配字符 a、i 或者 u 的字符集。
let bigStr = "big"; let bagStr = "bag"; let bugStr = "bug"; let bogStr = "bog";
let bgRegex = /b[aiu]g/;//字符集匹配 bigStr.match(bgRegex);//返回["big"] bagStr.match(bgRegex);//返回["bag"] bugStr.match(bgRegex);//返回["bug"] bogStr.match(bgRegex);//返回null
单个字母从单词检索也可实现,例如/[aeiou]/ig
- 元字符(shorthand character classes)
这些元字符缩写也被称为短语元字符
9.1 - (在[]中使用)
(适用于需要匹配大量字符的情况)
注意:如不使用i标签的话,会区分大小写。
(同时一般时搜索长句子,还应使用全局g标签)
通过使用连字符(-)来定义要匹配的字符范围。
let catStr = "cat"; let batStr = "bat"; let matStr = "mat"; let bgRegex = /[a-e]at/;//匹配了小写字母 a 到 e catStr.match(bgRegex);//返回["cat"] batStr.match(bgRegex);//返回["bat"] matStr.match(bgRegex);//返回null
使用连字符(-)匹配字符范围并不仅限于字母。 它还可以匹配一系列数字。例如,/[0-5]/ 匹配 0 和 5 之间的任意数字,包含 0 和 5。
let jennyStr = "Jenny8675309"; let myRegex = /[a-z0-9]/ig;// 此处为组合了字母和数字 jennyStr.match(myRegex);
9.2 + (匹配出现一次或者连续多次的的字符或字符组)
例:/a+/g
在 abc 中返回 ["a"]
在 aabc 中返回 ["aa"]
在 abab中返回["a", "a"](因为a字符不连续)
9.3 * (匹配出现零次或多次的字符)
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
9.4 $ (匹配字符串的结尾)
通过在正则表达式中使用$,形如/Ricky$/来实现匹配字符串结尾
返回true/false
9.5.1 \w (匹配字母数字下划线)
\w等同于[A-Za-z0-9_]
此字符类匹配上面字母和小写字母以及数字。
注意:这个字符类也包含下划线字符 (_)。
提示:可以通过使用元字符 \w 来计算所有引号中字母和数字字符的数量。
let quoteSample = "The five boxing wizards jump quickly."; let alphabetRegexV2 = /\w/g; // 不用+可用来计长 let result = quoteSample.match(alphabetRegexV2).length;
9.5.2 \W (匹配除字母数字下划线以外的全部)
\W是与\w相反的匹配模式
\W等同于[^A-Za-z0-9_]
let shortHand = /\W/; let numbers = "42%"; let sentence = "Coding!"; numbers.match(shortHand);//返回["%"] sentence.match(shortHand);//返回["!"]
9.6.1 \d (匹配所有数字)
\d等同于元字符[0-9]
9.6.2 \D (匹配所有非数字)
\D等同于元字符[^0-9]
9.7.1 \s (匹配空白字符)
使用\s将会匹配空格、回车符、制表符、换页符和换行符
等同于[ \r\t\f\n\v]
let whiteSpace = "Whitespace. Whitespace everywhere!" let spaceRegex = /\s/g; whiteSpace.match(spaceRegex);//将返回[" ", " "]
9.7.2 \S (匹配非空白字符)
此匹配模式将不匹配空格、回车符、制表符、换页符和换行符。
等同于[^ \r\t\f\n\v]。
let whiteSpace = "Whitespace. Whitespace everywhere!" let nonSpaceRegex = /\S/g; whiteSpace.match(nonSpaceRegex).length;//返回32
- 脱字符[^]
9.1/[^xxx]/否定字符集
通过在[]中使用脱字符^,排除所有否定字符集内的字符
例如,/[^aeiou]/gi 匹配所有非元音字符。
注意,字符 . 、! 、[ 、@ 、/ 和空白字符等也会被匹配
9.2/^x/匹配字符串开头
通过在正则表达式中使用^,形如/^Ricky/来实现匹配字符串开头
返回true/false
let firstString = "Ricky is first and can be found."; let firstRegex = /^Ricky/; firstRegex.test(firstString);//返回true let notFirst = "You can't find Ricky now."; firstRegex.test(notFirst);//返回false
- 贪婪匹配与懒惰匹配
贪婪(greedy)匹配会匹配到符合正则表达式匹配模式的字符串的最长可能部分,并将其作为匹配项返回。
贪婪匹配 /t[a-z]*i/ 返回为 ["titani"]("titanic")
可以使用 ? 字符来将转换成懒惰匹配
懒惰(lazy)匹配,它会匹配到满足正则表达式的字符串的最小可能部分。
转换后的懒惰匹配 /t[a-z]*?i/ 返回 ["ti"]("titanic")
表示只匹配ti
- /a{ x, y}/ 数量说明符(匹配花括号之前字母的重复次数)
匹配范围内出现次数的字符,如/{1,2}a/匹配出现1~2次的a字符
返回true or false
let A4 = "aaaah"; let A2 = "aah"; let multipleA = /a{3,5}h/;//仅匹配3~5次a加上h的字符 multipleA.test(A4);//返回true multipleA.test(A2);//返回false
注意:数量说明符仅匹配排在{ , }之前且在重复次数范围内的的字符。
12.1 /a{ x, }/ 只指定匹配的下限
只想指定匹配模式的下限时,在第一个数字后面跟一个逗号即可。
例如,要匹配至少出现 3 次字母 a 的字符串 hah,正则表达式应该是 /ha{3,}h/。
12.2 /a{x}/ 指定匹配的确切数量
通过在花括号中只写数量,来匹配明确的数量。
例如,要只匹配字母 a 出现 3 次的单词hah,正则表达式应为/ha{3}h/。
- /x?/检查是否存在的部分
(匹配问好之前的字母存在与否的字符串,是与否都返回true)
通过使用问号 ? 来匹配可能存在的元素。 这将检查前面的零个或一个元素。 可以将此符号视为前面的元素是可选的。
let american = "color"; let british = "colour"; let rainbowRegex= /colou?r/; rainbowRegex.test(american);//返回true rainbowRegex.test(british);//返回true
- 正向先行断言和负向先行断言(匹配方向)
正向先行断言 (?=...)
其中 ... 就是需要存在但不会被匹配的部分。
正向先行断言会查看并确保搜索匹配模式中的元素存在,但实际上并不匹配。
正向先行断言是告诉 JavaScript 在字符串中向前查找的匹配模式。
当想要在同一个字符串上搜寻多个匹配模式时,这可能非常有用。
负向先行断言 (?!...)
其中 ... 是希望不存在的匹配模式。
负向先行断言会查看并确保搜索匹配模式中的元素不存在
如果负向先行断言部分不存在,将返回匹配模式的其余部分
let quit = "qu"; let noquit = "qt"; let quRegex= /q(?=u)/; let qRegex = /q(?!u)/; quit.match(quRegex);//返回[“q”] noquit.match(qRegex);//返回[“q”]
先行断言的更实际用途是检查一个字符串中的两个或更多匹配模式
如例中一个简单的密码检查器,密码规则是 3 到 6 个字符且至少包含一个数字:
let password = "abc123";
let checkPass = /(?=\w{3,6})(?=\D*\d)/;
checkPass.test(password);
- 检查混合字符组
使用正则表达式里的括号 () 来检查字符组。
如果想在字符串找到 Penguin 或 Pumpkin,可以用这个正则表达式:/P(engu|umpk)in/g。
let testStr = "Pumpkin";
let testRegex = /P(engu|umpk)in/;
testRegex.test(testStr);//返回true
然后使用 test() 方法检查 test 字符串里面是否包含字符组。
- 使用捕获组搜寻重复的子字符串
使用捕获组搜寻重复的子字符串。 括号 ( xx ) 可以用来匹配重复的子字符串。
要指定重复字符串将出现的位置,可以使用反斜杠(\)后接一个数字。 这个数字从 1 开始,随着你使用的每个捕获组的增加而增加。 这里有一个示例,\1 可以匹配第一个组。
let repeatStr = "regex regex"; let repeatRegex = /(\w+)\s\1/; repeatRegex.test(repeatStr);//返回true repeatStr.match(repeatRegex);//返回["regex regex", "regex"]
调用 .match() 方法将返回一个数组,其中包含它最终匹配到的字符串及其捕获组。
let repeatNum = "42 42 42"; let reRegex = / ^(\d+)\s\1\s\1$ /;
//只匹配重复三次的字符串,开头结尾标签很重要
let result = reRegex.test(repeatNum);
在 reRegex 中使用捕获组来匹配一个只由相同的数字重复三次组成的由空格分隔字符串。
16.1使用捕获组搜索和替换
在字符串上使用 .replace( , ) 方法来搜索并替换字符串中的文本。
第一参数是想要搜索的正则表达式匹配模式
第二个参数是用于替换匹配的字符串或用于执行某些操作的函数。
let wrongText = "The sky is silver."; let silverRegex = /silver/; wrongText.replace(silverRegex, "blue"); //返回The sky is blue.
通过使用美元符号($)访问替换字符串中的捕获组。
"Code Camp".replace(/(\w+)\s(\w+)/, '$2 $1'); //返回Camp Code.
注意,此处2,1表示捕获组的位置,’$2 $1’表示位置互换
- 删除开头和结尾的空白
有时字符串周围存在的空白字符并不是必需的。
字符串的典型处理是删除字符串开头和结尾处的空格。
- 正则表达式的编写
编写一个用于检索数据库中的所有用户名的正则表达式。以下是用户在创建用户名时必须遵守的一些简单规则。
- 用户名只能是数字字母字符。
- 用户名中的数字必须在最后,数字可以有零个或多个,用户名不能以数字开头。
- 用户名字母可以是小写字母和大写字母。
- 用户名长度必须至少为两个字符。 两位用户名只能使用字母。
let username = "JackOfAllTrades"; let userCheck = /^\D[a-zA-Z]+\d*$|^\D\d\d+$|^[a-zA-Z][a-zA-Z]$/; /*-------------------------------------------------*/ ^\D[a-zA-Z]+\d*$ 开头必须是非数字,中间连续不能有数字,最后可连续数字,必须三位起 ^\D\d\d+$ 开头必须是非数字,后面可全是数字,但必须三位起 ^[a-zA-Z][a-zA-Z]$ 开头必须是数字,两位结尾允许不是数字 /*-------------------------------------------------*/ let result = userCheck.test(username);
结论:在编写较为复杂的正则表达式时,如果对前后字符有要求的,最好在所有的正则表达式上加上^开始位置元字符$结束位置元字符