zoukankan      html  css  js  c++  java
  • 正则表达式

      正则表达式,又叫规则表达式,我们写一个正则表达式,其实就是写一个规则,那么写一个规则干什么呢? 去匹配字符串,就是看看字符串中有哪个部分和我们定义的规则相符合,找到这些匹配的字符,我们就可以进行字符替换删除等操作,如下例子: 找到字符串中的所有数字,转化成字符G.  

    let reg = /d/g; // 定义一种规则,d 表示数字。
    let str = 'a4c5d6'
    let strReplaced = str.replace(reg,"G")
    console.log(strReplaced)    //  aGcGdG

      可以看到,正则表达式极大地方便了对字符串的操作。JS 是通过内置RegExp对象来支持正则表达式。既然是对象,那就有两种创建方式, 一种是对象字面量,一种是构造函数。

    // 对象字面量
    let regLiteral = /d/g;
    // 构造函数
    let regCons = new RegExp('\d', "g");

      构造函数使用不是太方便,一般都是使用字面量,只有在事先不确定的情况下需要动态生成时,才需要用到构造函数。

      2, 标识符: 上面的g 就是一个标识符,除了它,还有两个i, m

      g 是global,表示全局匹配。为什么会有这个标识符呢? 因为正则表达式匹配字符串时,默认是惰性匹配,就是,它只要成功匹配到一个,它就不会再进行匹配,把let reg = /d/g 中的g 去掉,

    let reg = /d/; 
    let str = 'a4c5d6'
    let strReplaced = str.replace(reg,"G")
    console.log(strReplaced)    //  aGc5d6

      可以看到,它只会匹配第一个数字4。从字符串的起始位置开始匹配,只要成功匹配到一个,就停止了, 即使字符串后面还有和正则表达式相匹配的,它也不管。加上g 标识符,就告诉正则表达式全部匹配,字符串中只要有和正则表达式相匹配的,就全部进行匹配,对应到替换字符,就是全部替换掉相符合的。

      i,是ignore, 忽略大小写。这很好理解, js就是区分大小写的,如果用一个大写字母去区配字符串的话,它只会去找字符串中的大写字母。如果加上i修饰符,就表示可以忽略大小写,小写字母也是ok的。

    // 没有加i标识符,可以看到它只会匹配字符串中的小写a
    let reg = /a/g;  
    let str = 'aAbbcc'
    let strReplaced = str.replace(reg,"G")
    console.log(strReplaced)    //  GAbbcc
    // 加i标识符,可以看到大写A小写a都会匹配 
    let reg = /a/gi;  
    let str = 'aAbbcc'
    let strReplaced = str.replace(reg,"G")
    console.log(strReplaced)    //  GGbbcc

      3, 正则表达式有两种基本字符组成,一种是原义文本字符,一种是元字符。原义文本字符,是指这个字符就是它本来的意思。let reg = /a/, a 就是小写字母a, 它也只会匹配小写字母a, 这就是它本来的意思,没有其他任何意思。 元字符,它是指有特殊含义的字符,如d, 它不是匹配 一根和小写字母d 的组合,d 表示的是任意的数字。 正则表达式中有以下元字符:. * ? ^ 等, 也就是说,这些字符都有特殊的意思.

      4, 字符类

      一般情况下,正则表达式在去匹配字符串的时候,都是一个字符一个字符的去匹配,也就是正则表达式中的一个字符对应字符串的一个字符。 但有时候,我们想让正则表达式中的多个字符去匹配一个字符,也就是,我们字符串中只要出现多个字符中一个就算匹配成功。比如,我们只要求字符串中有数字就行,而不管数字是哪个。这时就要用到[], 中括号中的字符,我们字符串中只要出现一个就ok.

    // []只要有中括号中的一个字符就算成功。
    let reg = /[0123456789]/g;  
    let str = 'a1b2c3d4'
    let strReplaced = str.replace(reg,"G")
    console.log(strReplaced)    //  aGbGcGdG

    可以看到,只要字符串中有一个数字,就算匹配成功。我们把所有的数字一一列出来,比较麻烦,如果有26个字母,我们要列了26个字母,这更麻烦了。还好正则表达式提供了范围的书写,0-9,a-z ,并且还可以连写。

    let reg =[0-9a-zA-z]

       在[]中其实还可以用一个字符,那就是^, 它表示取反。[^0-9] 就表示除了0-9之处的任意字符。[^0-9a-zA-z] 则表示除了0-9,a-z A-Z 之外的任意字符。对于这些常用的表示符,正则表达式也提供了一些预定义类,[0-9]表示数字,就可以用d 来代替,[^0-9] 表示非数字,可以用D来代替, 还有s, w, W等。 小写形式是什么,大写形式就是它的取反.

      d, d是digital 表示数字, 那么D 则表示不是数字; s, space 表示空白符, S就表示非空白符. w, word, 表示单词字符(字母,数字加下划线), W 表示非单词字符,这里还有一个 点号 . 它表示除回车和换行符之外的任意字符。我们写一个 ab 开始,后面紧跟数字,再后面是任意字符的正则表达式,let reg = /abd./

    let reg = /abd./g;
    let string = 'there is ab5td and abds '
    let replaceString = string.replace(reg,"A");
    console.log(replaceString)  // there is Ad and abds 

      这个正则表达式区配的是ab5t

      5, 边界类

      边界类主要用四个: ^ 表示以什么开始,$表示以什么结尾, , boudary 表示单词边界,B 表示非单词边界。边界就是单词和单词相隔的地方,最明显的就是空格。

    写一个例子来看一下可以更为直观。

    let reg = /is/g;
    let string = 'this is a dog '
    let replaceString = string.replace(reg,"IS");
    console.log(replaceString)  // thA IS a dog 

      两个is 都被替换掉了,这符合预期。但我们怎么只替换中间的is,中间的is 有一个特点,它是一个单词,因为前面和后面都是空格,使得它与其它单词分开了,正因为有空格的存在is 才成为了一个单词,所以空格是单词边界,  可以匹配到它。把正则表达式改成 /is/g, 可以看到输出 this IS a dog, 只匹配第二个。 如果只想改变第一个呢?那好办,因为第一个is被包含在一个单词中,所以它的前面不是单词边界,直接改成B 就可以了, 正则表达式改成 /Bis/g 就可以了.

      ^ 和$ 很好理解, /^T/以大写字母T开头即可, /T$/ 以大写字母T结束即可, 要注意它们的书写位置,一个在前,一个在后. 如果字符串中有换行符, let string = '@123 @456 @789', 字符串表现地就像有三行一样. 以下是chrome 浏览器中的输出

    这时如果以/^@/g 去进行匹配的话,它只会匹配第一个@,

    let reg = /^@/g;
    let string = '@123
    @456
    @789'
    let replaceString = string.replace(reg,"X");
    console.log(replaceString)  
    /* 
    *    X123
    *    @456
    *    @789
    */

      如果想匹配三个,那就要用到m修饰符,多行标示符,它表示如果字符串中有换行符,那就把字符串当成多行看待。m 标示符,只有在正则表达式中有^或&时才起作用,这也是把m标示符放到这里说明的原因。

      6 量词

      量词就是表示数量,一个字符出现了多少次。它有以下几种

      +:表示出现一次或多次(至少出现1次),+号吗,越加越多,越来越多,所以是多次。/ab+/, 字符串‘ab’, ‘abb’, ‘abbbbb......’ 都可以和它匹配。

      ? : 表示出现 0次或1次(最多出现1次), ? 表示是不是,是就是1, 不是就是是0, 所以表示0 或1. /ab?/ , 字符串‘a’, ‘ab’ 都可以和它匹配。

      * : 表示出现0,1 或多次, *都是通配符的意思, 通通匹配, 所以出现0次,1次或任意次都可以. /ab*/ , 字符串‘a’, ‘ab’ ,'abb', ‘abbbbb......’  都可以和它匹配。

      {n}:表示出现n次,如/d{5}/ 表示一个数字要出现5次,如 字符串‘12345’ 可以和它匹配

      {n,m}: 至少出现n次,最多出现m次  /d{3,5}/ , 字符串‘123’, ‘1234’, ‘12345’ 都可以和它匹配。

      {n, }: 至少出现 n次;  /d{2,}/   字符串‘12’, ‘123’, ‘12345’ , "12333....." 都可以和它匹配。

      如是在正则表达式中,出现量词,如/d{3,5}/, ‘123’, ‘1234’, ‘12345’ 都可以和它匹配,而我们的字符串是'123456', 那它怎么匹配,是区配字符串中 的 ‘123’, ‘1234’, 还是‘12345’ ? 这时正则表达式匹配最多出现次数,就是里面的12345, 这也称之为贪婪模式。 

    let reg = /d{3,5}/g;
    let string = '123456'
    let replaceString = string.replace(reg,"X");
    console.log(replaceString)  //X6, 可见它匹配的是12345,最多出现次数

      那怎么样才能让它匹配最小出现次数呢? 就是匹配出现3次,那也好办,就是在量词后面加? 正则表达式改为 /d{3,5}?/g, 这也称之为非贪婪模式或懒惰模式

    let reg = /d{3,5}?/g;
    let string = '123456'
    let replaceString = string.replace(reg,"X");
    console.log(replaceString)  //XX,123=> X, 456=> X,匹配最少次数

      对于非贪婪模式或贪婪模式,这里还要注意一点,先看一下下面的例子

    let reg = /d{3,5}/g;
    let string = '12345678'
    let replaceString = string.replace(reg,"X");
    console.log(replaceString)  //XX

      上面我们执行的是贪婪模式,它会匹配最多出现的次数,也就是5次,那么结果应该是X678才对,为什么是XX呢? 当贪婪模式匹配字符串的时候,当已经不够最大次数的匹配的时候,会选择更小次数的匹配。比如这里首先匹配12345, 剩下678, 它已经不够最大次数匹配,那就执行更小的次数匹配,那就是3或4,678 正好是3, 所以也就变成了X

      7 分组

      上面我们说过,正则表达式是一个字符一个字符的去匹配,所以如果要匹配一个单词如is ,就是必须写/is/, 如果想要匹配is 出现3次,就只能写/isisis/, 我们想使用量词/is{3}/,但这只表示s出现3次,那怎么修改才能表示is 出现三次,把is 用括号括起来,/(is){3}/. 用括号把is括起来,就表示是它是一个整体,一个组,它们要一起出现,才算匹配成功,所以称之为分组。分组有一个重要的概念,就是引用,当正则表达式中有分组时,我们可以获取到分组的内容,怎么获取,就是$n, n表示数字,$1 表示第一个分组的内容,$2 表示第二个分组的内容,$3 表示第三个分组的内容,依次类推,其实这里还有一个$0, 它比较特殊,所以单列出来,它表示,整个正则表达式匹配成功的内容。 可能不太好理解,写一个例子

    写一个时间字符串 '2017-03-05',  正则表达式 /d{4}-d{2}-d{2}/g 可以匹配它,如下,

    let reg = /d{4}-d{2}-d{2}/g;
    let string = '2017-03-20'
    let replaceString = string.replace(reg,"X");
    console.log(replaceString)  //X

      这时我们在正则表达式中加上分组,可以看到没有产生影响

    let reg = /(d{4})-(d{2})-(d{2})/g;  // 加上分组,就是把三段分别用括号括起来
    let string = '2017-03-20'
    let replaceString = string.replace(reg,"X");
    console.log(replaceString)  //X

      但是有了分组之后,就有引用,我们通过$n可以获取到分组内容,这里有三个分组,可以用$1, $2, $3 分别获取到三个分组内容, 把“X” 分别换成立$1,$2,$3看一个

      把replace 中的 “X” 换成$1, 可以看到输出2017, 表示$1获取的就是第一个分组 (d{4}) 的内容

    let reg = /(d{4})-(d{2})-(d{2})/g;  // 加上分组
    let string = '2017-03-20'
    let replaceString = string.replace(reg,"$1");
    console.log(replaceString)  //2017

      把replace 中的 “X” 换成$2, 输出03, 表示$2获取的就是第二个分组 (d{2}) 的内容, $3 可以自己试一下。

    let reg = /(d{4})-(d{2})-(d{2})/g; 
    let string = '2017-03-20'
    let replaceString = string.replace(reg,"$2"); // $2
    console.log(replaceString)  //03

      $1, $2,$3都是字符串,可以进行任意组合,我们就可以得到想要的结果, '$2/$3/$1', 我们就可以把一种日期格式,转化成另外一种日期格式

    let reg = /(d{4})-(d{2})-(d{2})/g; 
    let string = '2017-03-20'
    let replaceString = string.replace(reg,"$2/$3/$1"); 
    console.log(replaceString)  //  03/20/2017

      忽略分组:$n获取分组的内容和正则表达式中的分组是一一对应的,正则表达式中有几个分组,它从左向右就会对应几个$n, $1 永远获取的是第一个分组内容,$2 永远获取的都是第二个分组的内容,但有时候,我们想跳过某个分组,获取它下一个分组,比如$2 获取第三个分组的内容,这时正则表达式中的第二个分组前面要加 ?:, 表示获取内容的时候可以忽略这个分组

    let reg = /(d{4})-(?:d{2})-(d{2})/g; 
    let string = '2017-03-20'
    let replaceString = string.replace(reg,'$2'); // $2
    console.log(replaceString)  //20

      在上面的代码中,我们在第二个分组前面加了 ?:进行了忽略了,所以$2 获取的是第三个分组的内容。

      分组还有一个概念,就是重复子项,它用1,2来表示,它们只用在正则表达式中, 1 代表的也是第一个分组,2代表的是第二个分组,它们主要的作用是匹配以下这种字符串,

    、121, 222, 323, 424, 第一个数字和第三个数字相等,但又是不确定的数字, 所以在书写正则表达式时,必须保证第一项和第三项相等,第三项是第一项的复制,1, 就是正则表达式中第一个分组的复制。

    let reg = /(d)21/g; 
    let string = '121 222 323 424'
    let replaceString = string.replace(reg,'X');
    console.log(replaceString)  // X X X X

      还有一个或的概念,符号表示为|, /ab|ac/, 当它们去匹配字符串时,只要出现其中的一个就算成功

  • 相关阅读:
    一句话解释c#中的特性,你了解多少
    CentOS虚拟机如何设置共享文件夹,并在Windows下映射网络驱动器?
    samba服务器配置及window网络磁盘映射
    PHP中各种Hash算法性能比较
    Redis持久化
    设置redis主从出现的问题
    Redis启动多端口、运行多实例
    Redis学习手册(主从复制)
    tengine/nginx-tomcat动静分离遇到的问题
    使用 Git Hooks 实现自动项目部署
  • 原文地址:https://www.cnblogs.com/SamWeb/p/6653994.html
Copyright © 2011-2022 走看看