JS 掌握正则表达式

2019-04-11  本文已影响0人  ER_PM

如果你没有经历过失败,就说明你没有努力突破极限,而如果你不努力突破极限,你就不能最大限度的挖掘自己的潜能。

正则表达式,对程序员来说在工作中具有非常重要的地位,主要用来匹配或者替换指定字符串,它的功能非常强大,既简单又复杂,掌握它将会让你在编程中如虎添翼。

内容:

创建匹配模式/Regex/

先来简单认识下它吧,如果你想在"Hello, World!"字符串中匹配到"Hello",这个单词,那么如何创建这个正则表达式呢?只需要/Hello/,用两根筷子夹在它身边就ok了!

test()方法

创建好正则/Hello/后,使用test(),它会把匹配模式应用到你的内容,如匹配到则返回true,否则返回false。请看下面例子:

tips:默认区分大小写

let myString = "Hello, World!";
let myRegex = /Hello/;
let result = myRegex.test(myString); // 返回true

多种匹配模式匹配字符串

多种匹配模式使用|来分隔多种匹配模式,表示或者的意思,例如:你想匹配yes或者no,你的正则表达式是这么写:/yes|no/

下面这个例子,只要petRegex这个正则表达式匹配到petString中包含有dog或cat或bird或fish,result都等于true。

let petString = "James has a pet cat.";
let petRegex = /dog|cat|bird|fish/; 
let result = petRegex.test(petString);

匹配时忽略大小写

正则表达式对于英文字母的匹配模式默认是大小写敏感的,但是如何才能去掉这个限制呢?就是不区分大小写呢?很简单在正则后背添加i即可。

/ignorecase/i,可以匹配"ignorecase""igNoreCase""IgnoreCase"等字符串。

提取匹配项match()方法

字符串的match()方法,接收一个正则匹配模式为参数,把匹配到的内容提取出来并返回一个新数组。

"Hello, World!".match(/Hello/);
// Returns ["Hello"]
let ourStr = "Regular expressions";
let ourRegex = /expressions/;
ourStr.match(ourRegex);
// Returns ["expressions"]

全局匹配

到目前为止,你只能执行一次匹配模式或一次提取数据而已,但如何提取或匹配所有相关的内容呢?请看下面的答案:

g表示该正则表达式是全局匹配或称多次匹配,可与i配合使用,gi表示全局匹配和不区分大小写匹配

let repeatRegex = /Repeat/g;
testStr.match(repeatRegex);
// Returns ["Repeat", "Repeat", "Repeat"]
let twinkleStar = "Twinkle, twinkle, little star";
let starRegex = /Twinkle/gi; 
let result = twinkleStar.match(starRegex); 
//Returns [Twinkle, twinkle]

用通配符.匹配任何内容

前面的讲解都是精确匹配,而/./是匹配所有。

通配符的匹配模式我更认为是叫模糊匹配符,有时候你想匹配某个单词,但你只清楚它的其中几个字母的构造,这时候你就可以使用通配符来占位你不确定的字母,这样它就可以帮你把相关的单词给匹配出来。

例如,如果你想匹配"hug""huh""hut""hum",你可以使用正则表达式/hu./匹配以上四个单词

let humStr = "I'll hum a song";
let hugStr = "Bear hug";
let huRegex = /hu./;
humStr.match(huRegex); // Returns ["hum"]
hugStr.match(huRegex); // Returns ["hug"]

多种可能性匹配[]

[],填入1个或1个以上字符就可以创建多种可能的匹配模式,例如,你想要匹配"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); // Returns ["big"]
bagStr.match(bgRegex); // Returns ["bag"]
bugStr.match(bgRegex); // Returns ["bug"]
bogStr.match(bgRegex); // Returns null

连字符(-)匹配字符集

假如你想匹配字符集里某个范围内的任意字符,那么你可以使用连字符-来进行连接,表示字符和另一个字符之间的集合。

例如,要匹配小写字母ae,你可以使用[a-e],[a-z]则匹配所有小写字符。

let catStr = "cat";
let batStr = "bat";
let matStr = "mat";
let bgRegex = /[a-e]at/;
catStr.match(bgRegex); // Returns ["cat"]
batStr.match(bgRegex); // Returns ["bat"]
matStr.match(bgRegex); // Returns null

连字符-匹配字符串中的字符和数字

连字符不仅可以应用于字符,还可以应用于数字。比如,[0-5],则匹配05之间的任意数字。所以你还可以跟一系列字符和数字组合起来使用。

let jennyStr = "Jenny8675309";
let myRegex = /[a-z0-9]/ig;
//myRegex表示匹配jennyStr中所有的字母和数字
jennyStr.match(myRegex);

匹配非指定字符

在你不想匹配的字符前插入^这个符号,即可创建排除字符集的表达式。
例如,/[^aeiou]/gi匹配所有非元音字符。注意,字符.、!、[、@、/和空白字符等也会被匹配,该否定字符集仅排除元音字符。

下面创建了一个匹配所有非数字或元音字符的正则表达式。

let quoteSample = "3 blind mice.";
let myRegex = /[^0-9aeiou]/ig; 
let result = quoteSample.match(myRegex); // 返回[,b,l,n,d, ,m,c,.]

+ 匹配出现1次或1次以上的字符

有时,你需要匹配出现1次或连续出现多次的字符(或字符组),这时候你可以使用符号+

例如,/a+/g会在"abc"中匹配到一个匹配项,并且返回["a"]。因为+的存在,它也会在"aabc"中匹配到一个匹配项,然后返回["aa"]

let difficultSpelling = "Mississippi";
let myRegex = /s+/g; 
let result = difficultSpelling.match(myRegex);
console.log(result)//返回["ss","ss"]

* 匹配出现0次或1次以上的字符

+是匹配1次或1次以上,表示的是匹配0次或1次以上的字符,如下,正则/go/,表示匹配"g"及其后面出现0次或多次以上的"o"

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

? 使用惰性匹配来查找字符

正则表达式的默认匹配模式是贪婪匹配(尽可能的多的匹配),惰性匹配呢?(意思是尽可能少的匹配)。

例如:你可以将正则表达式/t[a-z]*i/应用于字符串"titanic"。这个正则表达式是一个以t开始,以i结束,并且中间有一些字母的匹配模式。

贪婪匹配最后返回["titani"],它会尽可能多的匹配。

假如你想使用尽可能少的匹配(惰性匹配),可以使用?,如:/t[a-z]*?i/,所以[a-z]区间的字母会被尽可能的忽略,所以最后则给你返回["ti"]

let text = "titanic";
let myRegex1 = /t[a-z]*i/; //默认贪婪匹配
let myRegex2 = /t[a-z]*?i/; //惰性匹配
let result1 = text.match(myRegex1);  //["titani"]
let result2 = text.match(myRegex2);//["ti"]

匹配字符串的开头

^符号放在字符集中表示否定,但是把^放在字符的外面的最头部,表示匹配字符串的开头,例如:

let firstString = "Ricky is first and can be found.";
let firstRegex = /^Ricky/;
firstRegex.test(firstString);
// Returns true
let notFirst = "You can't find Ricky now.";
firstRegex.test(notFirst);
// Returns false

$匹配字符串的结尾

^以字符串开头作为匹配模式,$是以字符串的结尾作为匹配模式。例如:/story$/表示字符串的末尾为"story"才会匹配成功。

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匹配所有单个字母和数字

\w[A-Za-z0-9_]的缩写,记住,它还会匹配下划线字符(_)

let longHand = /[A-Za-z0-9_]+/;
let shortHand = /\w+/;
let numbers = "42";
let varNames = "important_var";
longHand.test(numbers); // Returns true
shortHand.test(numbers); // Returns true
longHand.test(varNames); // Returns true
shortHand.test(varNames); // Returns true

下面是统计quoteSample中字母和数字字符的数量

let quoteSample = "The five boxing wizards jump quickly.";
let alphabetRegexV2 = /\w/g; 
let result = quoteSample.match(alphabetRegexV2).length;
//result 等于31

\W匹配除了字母和数字的所有单个符号

\w匹配所有单个的字母和数字符号,\W则正好相反,是[^A-Za-z0-9_]的缩写,通常相反的匹配模式用大写字母来表示。

let shortHand = /\W/;
let numbers = "42%";
let sentence = "Coding!";
numbers.match(shortHand); // Returns ["%"]
sentence.match(shortHand); // Returns ["!"]

\d匹配所有数字

\d 等同于[0-9],匹配09之间任意数字的单个字符。

let string = "Catch 2";
let numRegex = /\d/; 
let result = string.match(numRegex);
//result 等于["2"]

\D匹配所有非数字

小写\d是表示查找所有数字,大写\D正好相反,等同于[^0-9],匹配所有非数字。

let numString = "Your sandwich will be $5.00";
let noNumRegex = /\D/g; 
let result = numString.match(noNumRegex).length;
//result 等于24

匹配空白字符

\s 可以匹配字符之间的空格,它还匹配回车符制表符换页符换行符,你可以将其视为与[\r\t\f\n\v]类似。

let whiteSpace = "Whitespace. Whitespace everywhere!"
let spaceRegex = /\s/g;
whiteSpace.match(spaceRegex);
// Returns [" ", " "]

匹配非空白字符

\s来搜寻空白字符,\S则搜寻除了空白字符之外的字符。此匹配模式将不匹配空格回车符制表符换页符换行符。你可以认为这类似于字符类[^\r\t\f\n\v]

let whiteSpace = "Whitespace. Whitespace everywhere!"
let nonSpaceRegex = /\S/g;
whiteSpace.match(nonSpaceRegex).length; // Returns 32

指定匹配的上限和下限{}

{} 可以通过数字设置上限和下限来限定匹配字符的出现个数,例如,要在字符串"ah"中匹配仅出现35次的字母a,你的正则表达式应为/a{3,5}h/

let A4 = "aaaah";
let A2 = "aah";
let multipleA = /a{3,5}h/;
multipleA.test(A4); // Returns true
multipleA.test(A2); // Returns false

指定可选的元素(? 0或1个)

有时候你的匹配模式无法确定存在的部分,那么你可以使用? 来表示0个或1个,你可以将此符号视为前面的元素是可选的。

例如,美式英语和英式英语略有不同,你可以使用问号来匹配两种拼写

let american = "color";
let british = "colour";
let rainbowRegex= /colou?r/;
rainbowRegex.test(american); // Returns true
rainbowRegex.test(british); // Returns true

正向先行断言和负向先行断言

先行断言可以在同一个字符串上搜寻多个匹配模式。有两种先行断言正向先行断言负向先行断言

正向先行断言会查看并确保搜索匹配模式中的元素存在,但实际上并不匹配。正向先行断言的用法是(?=...),其中...就是需要存在但不会被匹配的部分,将返回匹配模式的其余部分。

负向先行断言会查看并确保搜索匹配模式中的元素不存在。负向先行断言的用法是(?!...),其中...是你希望不存在的匹配模式。如果负向先行断言部分不存在,将返回匹配模式的其余部分。

实例:

let quit = "qu";
let noquit = "qt";
let quRegex= /q(?=u)/;
let qRegex = /q(?!u)/;
quit.match(quRegex); // Returns ["q"]
noquit.match(qRegex); // Returns ["q"]

一个简单的密码检查器,密码规则是 3 到 6 个字符且至少包含一个数字:

let password = "abc123";
let checkPass = /(?=\w{3,6})(?=\D*\d)/;
checkPass.test(password); // Returns true

使用捕获组重复使用

有时候需要使用到多次重复的匹配模式,重复编写表达式是非常繁琐的,这时候就可以使用捕获组来解决这个问题。

捕获组搜寻重复的子字符串。括号()可以用来匹配重复的子字符串。你只需要把重复匹配模式的正则表达式放在括号中即可。

要指定重复字符串将出现的位置,可以使用反斜杠(\)后接一个数字。这个数字从 1 开始,随着你使用的每个捕获组的增加而增加。这里有一个示例,\1可以匹配第一个组。

let repeatStr = "regex regex";
let repeatRegex = /(\w+)\s\1/;
repeatRegex.test(repeatStr); // Returns true
repeatStr.match(repeatRegex); // Returns ["regex regex", "regex"]

["regex regex", "regex"],该数组index1的元素是捕获组匹配到的元素。

let testString = "test test test test test test";
let reRegex =/(test)(\s)\1\2\1/g; //这里的2表示(\s)
let result = reRegex.test(testString);

replace(regex,str) 字符串正则替换

字符串.replace()方法来搜索并替换字符串中的文本。.replace()的第1个参数为正则表达式匹配模式,第2个参数是用于替换匹配的字符串或用于执行某些操作的函数。

let wrongText = "The sky is silver.";
let silverRegex = /silver/;
let result = wrongText.replace(silverRegex, "blue");
// Returns "The sky is blue."

你还可以使用美元符号($)访问替换字符串中的捕获组。

"Code Camp".replace(/(\w+)\s(\w+)/, '$2 $1'); //本身替换本身
// Returns "Camp Code"

删除字符串的开头和结尾的空格

let hello = "   Hello, World!  ";
let wsRegex = /^\s+|\s+$/g; // 修改这一行
let result = hello.replace(wsRegex,''); // 修改这一行
//Returns "Hello, World!"

注:.trim()方法在这里也可以实现同样的效果

上一篇下一篇

猜你喜欢

热点阅读