美文网首页
JS 掌握正则表达式

JS 掌握正则表达式

作者: ER_PM | 来源:发表于2019-04-11 22:59 被阅读0次

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

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

    内容:

    • 创建匹配模式
    • test()方法
    • 多种匹配模式匹配字符串
    • 匹配时忽略大小写
    • 提取匹配项match()方法
    • 全局匹配
    • 用通配符.匹配任何内容
    • 多种可能性匹配[]
    • 连字符(-)匹配字符集
    • 连字符-匹配字符串中的字符和数字
    • 匹配非指定字符
    • 匹配出现1次或1次以上的字符
    • 匹配出现0次或1次以上的字符
    • 使用惰性匹配来查找字符
    • 匹配字符串的开头
    • $匹配字符串的结尾
    • \w匹配所有单个字母和数字
    • \W匹配除了字母和数字的所有单个符号
    • \d匹配所有数字
    • \D匹配所有非数字
    • 匹配空白字符
    • 匹配非空白字符
    • 指定匹配的上限和下限{}
    • 指定可选的元素(? 0或1个)
    • 正向先行断言和负向先行断言
    • 使用捕获组重复使用
    • replace(regex,str) 字符串正则替换
    • 删除字符串的开头和结尾的空格

    创建匹配模式/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/

    • {n,}:至少匹配n个以上,n是一个非负整数
    • {n}:精确匹配n次,如/o{2}/,匹配2o,n是一个非负整数
    • {m,n}: 其中n <= m,最少匹配n次且最多匹配 m
    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()方法在这里也可以实现同样的效果

    相关文章

      网友评论

          本文标题:JS 掌握正则表达式

          本文链接:https://www.haomeiwen.com/subject/mkawiqtx.html