1. 使用regex.test(string)测试方法(Using the Test Method)
正则表达式被用于匹配符合条件的字符串
比方说,你想要匹配“what are you fucking doing!”中的fucking,可以通过/fucking/匹配(/”/“不是正则表达式中所必需的,每种语言中插入正则表达式的方式都不同,但是正则的语法都相同)。
JS有许多方式可以应用正则表达式,其中一种测试正则表达式的方法就是regex.test(string)方法,该方法被正则表达式调用,如果匹配成功则返回true,否则返回false。
let testStr = "freeCodeCamp";
let testRegex = /Code/;
testRegex.test(testStr); //true
//or
console.log(/code/.test("like code")); //true
test()属于严格匹配,即他不会匹配其他格式的相同字符串(如,大小写差异等),如:
let wrongRegex = /CODE/;
wrongRegex.test(testStr);// false
使用" | "匹配多个不同元素,如:
let petString = "James has a pet cat.";
let petRegex = /dog|cat|bird|fish/;
let result = petRegex.test(petString);
使用“ i ”(ignore)忽略大小匹配,如:
let fccRegex = /freeCodeCamp/i;
2.使用string.match(regex)方法获取匹配项
"Hello, World!".match(/Hello/); // Returns ["Hello"]
let ourStr = "Regular expressions";
let ourRegex = /expressions/;
ourStr.match(ourRegex); // Returns ["expressions"]
上述方法只能返回首次匹配到的对象,可使用" g "多次匹配正确对象:
let repeatRegex = /Repeat/g;
testStr.match(repeatRegex); // Returns ["Repeat", "Repeat", "Repeat"]
使用" /…/ig "多次返回忽略大小比较的匹配。
注意:返回match()方法返回的对象是数组
3.使用通配符匹配不定字符对象
- 使用‘’ . “匹配任意字符
let humStr = "I'll hum a song";
let hugStr = "Bear hug";
let huRegex = /hu./;
humStr.match(huRegex); // Returns ["hum"]
hugStr.match(huRegex); // Returns ["hug"]
- 使用” [ ] “匹配限定字符,如:/b[aiu]g/ 只会匹配,bag,bug,big,而不会匹配bog等:
let bigStr = "big";
let bagStr = "bag";
let bugStr = "bug";
let bogStr = "bog";
let bgRegex = /b[aiu]g/;
bigStr.match(bgRegex); // Returns ["big"]
bagStr.match(bgRegex); // Returns ["bag"]
bugStr.match(bgRegex); // Returns ["bug"]
bogStr.match(bgRegex); // Returns null
- 在英文字母的范围内,使用” [ - ] “匹配字母表中两个字母间的任意字符,如[a-z],匹配a到z范围内的任何小写字符,又如:
let catStr = "cat";
let batStr = "bat";
let matStr = "Mat";
let bgRegex = /[a-e]at/i;
catStr.match(bgRegex); // Returns ["cat"]
batStr.match(bgRegex); // Returns ["bat"]
matStr.match(bgRegex); // Returns null
[ - ]也可用于匹配连续的数字,如:/[1-9]/匹配1-9之间的任意数字,还可以将数字与字母结合起来,如:/[1-5a-v]/匹配1-5之间的任意数字,或者1-5之间的任意字母。
-
(negated character sets)[ ^ ],使用否定字符集匹配不包含指定字符集的字符集,如,使用
/[ ^aeiou ]/gi 匹配所有不是元音字符的字符(不区分大小写) -
使用/a+/匹配单个或连续个a字符集,a至少出现一次,比如,/a+/匹配”daab“返回[“aa”],匹配”sdaga“返回[a]
注:/ab+/只会匹配一个a和多个b同时出现的情况:
let soccerWord = "gggooooooooal!";
let goRegex = /go+/;
soccerWord.match(goRegex); // Returns ["goooooooo"]
使用/a*/匹配0个或多个a字符集:
let soccerWord = "gooooooooal!";
let gPhrase = "gut feeling";
let oPhrase = "over the moon";
let goRegex = /go*/;
soccerWord.match(goRegex); // Returns ["goooooooo"]
gPhrase.match(goRegex); // Returns ["g"]
oPhrase.match(goRegex); // Returns null
注:上述两种匹配都属于贪婪匹配(greedy match),即后面有多少满足条件就继续往后匹配多少。正则表达式默认都是贪婪匹配的,如/a[a-z]i/匹配字符串“avbhiidi”返回[“avbhiidi”]
- 使用?实现懒惰匹配并返回满足条件的最短的匹配成功字符集,如:
let text = "hifgjfiifdhi";
let myRegex = /h[a-z]*?i/;
let result = text.match(myRegex); //return ["hi"]
- 使用" ^ "来匹配字符串的开始位置,如:
let reg4 = /^aei/;
let str4_1 = "aeiooo";
let str4 = "you are only a aeiou";
console.log(str4_1.match(reg4)[0]); //return ["aei"]
console.log(str4.match(reg4)[0]); //error:str4.match(reg4)==null
- 使用“ $ ”来匹配字符串的末尾:如:
let theEnding = "This is a never ending story";
let storyRegex = /story$/;
storyRegex.test(theEnding); // Returns true
let noEnding = "Sometimes a story will have to end";
storyRegex.test(noEnding); // Returns false
- 使用/\w+/() 匹配所有的字母和数字以及下划线,此通配符等价于/[a-zA-Z0-9_]+/
let quoteSample = "The five boxing wizards jump quickly.";
let alphabetRegexV2 = /\w?/g;
let alphabetRegexV21 = /\w+?/g;
let result = quoteSample.match(alphabetRegexV2).length;
console.log(result);
console.log(quoteSample.match(alphabetRegexV21).length);
使用/ \W /()大写匹配所有/ \w /匹配不到的字符,即相当于/[ ^a-z0-9A-Z_]/
let shortHand = /\W/;
let numbers = "42%";
let sentence = "Coding!";
numbers.match(shortHand); // Returns ["%"]
sentence.match(shortHand); // Returns ["!"]
- 使用/\d/ (digit)匹配所有数字,此操作符等价于/[0-9]/
使用/\D/匹配所有不是数字的字符,此操作等价于/[^0-9]/
- 使用/\s/(space)匹配空格“ ”,换行符,制表符,回车符,换页符,此操作等价于/[ \r\t\f\n\v]/
\f | 匹配一个换页 |
---|---|
\n | 匹配一个换行符 |
\r | 匹配一个回车符 |
\t | 匹配一个制表符 |
\v | 匹配一个垂直制表符 |
如:
let whiteSpace = "Whitespace. Whitespace everywhere!"
let spaceRegex = /\s/g;
whiteSpace.match(spaceRegex);
// Returns [" ", " "]
使用/\S/匹配所有的非/\s/之外的符号,此符号等价于/[^ \t\r\f\n\v]/,如:
let whiteSpace = "Whitespace. Whitespace everywhere!"
let nonSpaceRegex = /\S/g;
whiteSpace.match(nonSpaceRegex).length; // Returns 32
- 用数量说明符(quantity specifiers)匹配一定数量范围的的字符
用/a{x,y}/表示匹配a字符x-y之间次:
let A4 = "aaaah";
let A2 = "aah";
let multipleA = /a{3,5}h/;
multipleA.match(A4); // aaaah
multipleA.test(A2); // Returns false
//and
let reg7=/a{2,4}/;
console.log("aaa".match(reg7)[0])
用/a{x, }/匹配至少x次字符a:
let A4 = "haaaah";
let A2 = "haah";
let A100 = "h" + "a".repeat(100) + "h";
let multipleA = /ha{3,}h/;
multipleA.test(A4); // Returns true
multipleA.test(A2); // Returns false
multipleA.test(A100); // Returns true
用/a{x}/匹配字符a正好x次:
let A4 = "haaaah";
let A3 = "haaah";
let A100 = "h" + "a".repeat(100) + "h";
let multipleHA = /ha{3}h/;
multipleHA.test(A4); // Returns false
multipleHA.test(A3); // Returns true
multipleHA.test(A100); // Returns false
- 可选匹配(?),/a?/,表示如果a存在则匹配一次,否则,不匹配。如:
let str8 = "coloor";
let str8_1 = "color";
let str8_2 = "colr";
let reg8= /colo*?r/;
let reg8_1= /colo?r/;
console.log(str8.match(reg8)[0]) //coloor
reg8_1.test(str8_1); //true
reg8_1.test(str8); //false
reg8_1.test(str8_2) //true
注意:懒匹配与可选匹配之间的区别
" abcd".match(/[c-z]?/g).length // 7,例1
“abcd”.match(/z?/).length // 1 ,例2
以上都属于可选匹配
“abcd”.match(/z/).length //error there have no array ,例3
以下是懒匹配
“abcd”.match(/a.?d/) // ad
“abcd”.match(/.?/) // null,数组长度等于一,但元素值为null,而不会报错
即懒匹配表示匹配尽量少个字符,对于懒匹配当无匹配元素时,?懒匹配不会返回任何匹配的元素到数组,但数组长度依然加一,元素表示null。
[c-z]表示匹配1个小写字母,对于例3没有懒匹配的情况下,在未匹配到有效元素的情况下不会添加任何对象进数组。
而[c-z]*?表示匹配尽量少个有效字符,即最少可以匹配到0个正确字符,此时对于符合条件的字符,懒匹配依然不会添加任何字符进数组,但字符长度依然加一。
X? | 一次或一次也没有 |
---|---|
X* | 零次或多次 |
X+ | 一次或多次 |
X{n} | 恰好 n 次 |
X{n,} | 至少 n 次 |
X{n,m} | 至少 n 次,但是不超过 m 次 |
– | – |
X?? | 一次或一次也没有 |
X*? | 零次或多次 |
X+? | 一次或多次 |
X{n}? | 恰好 n 次 |
X{n,}? | 至少 n 次 |
- 零宽正向先行断言(?=A)与零宽负向先行断言(?!B)(Positive and Negative Lookahead)
零宽正向先行断言即在匹配之前所要进行的必要性检查,即检查条件A是否存在(注意是在接下来要匹配的字符串的基础之上),如果存在,则继续下一步,而段言中的内容只做检查,不会参与匹配成功后返回的字符串中,如果条件A不存在,则匹配终止。例如:
let reg9_2 = /bana12(?=\w{5})tt(?=\d{2})12(?=fg)/;
let str9 = "bana12tt12fgjf"
console.log(.match(reg9_2)[0]); //bana12tt12
上段代码中,首先 /bana12-/匹配str9中的“bana12”部分《1》,之后/-(?=\w{5})-/立即检查紧跟《1》其后的字符串中是否含有5个\w字符,如果有,则/- tt -/继续匹配从《1》往后匹配内容“tt”《2》,又匹配成功,此时又进行断言/- (?=\d{2}) -/,判断《2》之后是否有两个数字,如果有,则继续匹配,在之后,/- 12 -/从《2》内容处开始往后匹配12《3》,匹配成功,又进行检查,/- (?=fg) -/判断《3》之后是否紧跟字母“fg”,如果是,则返回匹配成功的字符串进数组“bana12tt12”.
而零宽负向先行断言与之大同小异,只是匹配之前检查条件B是否不存在,然后进行匹配。
又例如
let quit = "qu";
let noquit = "qt";
let quRegex= /q(?=u)/;
let qRegex = /q(?!u)/;
quit.match(quRegex); // Returns ["q"]
noquit.match(qRegex); // Returns ["q"]
注意:当*与零宽先行断言一起连用时:(是个坑啊!!)
let p1= "astronaut".match(/.*(?=\w{6,})/); //return null,(数组长度人仍加1)
let p2= "astronaut".match(/.*(?=\w{5,})/); //return a
let p3= "astronaut".match(/.*(?=\w{4,})/); //return as
.
.
//和+与零宽先行断言一起连用时:
let p1= "astronaut".match(/.+(?=\w{6,})/); //return error,there have no array
let p2= "astronaut".match(/.+(?=\w{5,})/); //return a
.
.
//即此处的贪婪匹配,会根据前后条件进行选择,变得不那么纯粹。
又例:
let s = "astr23";
let p= s.match(/.*(?=\D*\d(2))(?=\w{6,})/); //return null,(数组长度仍加1)
//此处/.*-/先根据/-(?=\w{6,})/断言,匹配最多0个字符《1》,再根据断言
/-(?=\D{4}\d{2})-/判断《1》之后是否立即紧跟着四个非数字和两个数字,匹配成功《2》,
在根据/-(?=\w{6,})-/断言判断《1》之后是否紧跟着6个\w字符,匹配成功,返回null,数组长度加1.
还有正向后行断言(?<=pattern),与负向后行断言(?<!pattern)
(?=pattern) 正向先行断言 | 代表字符串中的一个位置,紧接该位置之后的字符序列能够匹配pattern。 |
---|---|
(?!pattern) 负向先行断言 | 代表字符串中的一个位置,紧接该位置之后的字符序列不能匹配pattern。 |
(?<=pattern) 正向后行断言 | 代表字符串中的一个位置,紧接该位置之前的字符序列能够匹配pattern。例如对”regex represents regular expression”这个字符串,有4个单词,要想匹配单词内部的re,但不匹配单词开头的re,可以用”(?<=\w)re”,单词内部的re,在re前面应该是一个单词字符。之所以叫后行断言,是因为正则表达式引擎在匹配字符串和表达式时,是从前向后逐个扫描字符串中的字符,并判断是否与表达式符合,当在表达式中遇到该断言时,正则表达式引擎需要往字符串前端检测已扫描过的字符,相对于扫描方向是向后的。 |
(?<!pattern) | 负向后行断言代表字符串中的一个位置,紧接该位置之前的字符序列不能匹配pattern。例如对”regex represents regular expression”这个字符串,要想匹配单词开头的re,可以用”(?<!\w)re”。单词开头的re,在本例中,也就是指不在单词内部的re,即re前面不是单词字符。当然也可以用”\bre”来匹配。 |
- 表达式复用,例如:
let repeatStr = "regex regex";
let repeatRegex = /(\w+)\s\1/; //\1表示(\w+),此后该正则表达式中只要有用到该
//括号中内容的地方都可以用”\1“代替
repeatRegex.test(repeatStr); // Returns true
repeatStr.match(repeatRegex); // Returns ["regex regex", "regex"] //返回的数组中,
//第一个元素表示匹配成功后的字符串,第二个元素表示“\1”
又例如:
let Num2 = "42s8j42s8j4242s8j42s8j42";
let r2 = /(\d+)(s)(8)(j)\1\2\3\4\1/;
console.log(Num2.match(r2).length+"-LONG") //5-LONG
for(var i=0 ;i<Num2.match(r2).length;i++) console.log(Num2.match(r2)[i]+"——");
//42s8j42s8j42—— 42—— s—— 8—— j——
let r3 = /(\d+)(s)(8)(j)\1\2\3\4\1/g;
console.log(Num2.match(r3).length+"-LONG") //2-LONG
for(var i=0 ;i<Num2.match(r3).length;i++) console.log(Num2.match(r3)[i]+"——");
//42s8j42s8j42—— 42s8j42s8j42——
即当匹配的结果只有一个时,各被省略的表达式也会被返回进数组,但当匹配的结果有多个时,便只会返回正常匹配成功的多个元素进数组,而被省略的表达式不再被添加进数组。
- 使用string1.replace(regex,string2)或者string1.replace(regex,function) 或者string1.replace(substring,string2)以string2或function操作替代string1中被regex匹配到的字符(或者substring子字符串)。如:
let wrongText = "The sky is silver.";
let silverRegex = /silver/;
wrongText.replace(silverRegex, "blue"); // Returns "The sky is blue."
你可以使用“$+数字“ 表示被成功匹配的元素,如下代码中,$1即表示”Code“,$2即表示”Camp“(注意:如果想采用这种方式代替元素,被表示部分的正则表达式需要用()包围,如,下例中的(\w+),(\w{4}),(8))
"Code Camp8".replace(/(\w+)\s(\w{4})(8)/, '$2$3$1'); // Returns "Camp8Code"