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

    2.“或”匹配

      有的时候,我们要取消某段文字中的加粗、斜体等效果,我们想匹配所有的“<b>”、“</b>” 或者 “<i>”、“</i>”,然后把它们替换成空,仅利用之前的知识,我们只能

    进行两次匹配和替换,一次是“</?b>”,一次是“</?i>”。

          在正则表达式中,可以使用“|”将一个表达式拆分成两部分“reg1|reg2”,它的意思是:匹配所有符合表达式reg1的文本 或者 符合表达式reg2的文本。

    对于本节提出的问题,可以这样进行解决:

    Text

      The <b>text of</b> this row is bold.

      The <i>text of</i> this row is italic.

    RegEx

      </?i>|</?b>

    Result

      The <b>text of</b> this row is bold.

      The <i>text of</i> this row is italic.

    3.在子模式中使用“或”匹配

      从上面的定义应该可以看出,“|”分隔的是整个表达式,而有的时候,我们希望分隔的是一个表达式的一部分,比如说,我们想要匹配 “1900”到“2099”的所有年份。

    Text

      1932 is supposed to be matched as a whole, but it is matched only part of it.

      2055 is mathced in the right way.

      3019 is out of range, but it's still matched partly.

    RegEx

      19|20\d{2}

    Result

      1932 is supposed to be matched as a whole, but it is matched only part of it.

      2055 is mathced in the right way.

      3019 is out of range, but it's still matched partly.

    可以看到,表达式“19|20\d{2}”要么匹配“19”,要么匹配“20\d{2}”。而我们希望的是匹配“19\d{2}”或者“20\d{2}”,当然,我们可以改写上面的表达式为“19\d{2}

    |20\d{2}”来完成,但是,利用本章所讲述的子模式,可以更加简洁地完成这个过程。

    Text

      1932 is supposed to be matched as a whole, but it is matched only part of it.

      2055 is mathced in the right way.

      3019 is out of range, but it's still matched partly.

    RegEx

      (19|20)\d{2}

    Result

      1932 is supposed to be matched as a whole, but it is matched only part of it.

      2055 is mathced in the right way.

      3019 is out of range, but it's still matched partly.

      这次,我们得到了想要的结果,使用子模式可以简化匹配表达式。

      NOTE:有点类似于数学中的提取公因式:2*3 + 7*3 = (2+7)*3 --> 19\d{2}|20\d{2} = (19|20)\d{2}

    4.嵌套子模式

      子模式可以再继续嵌套子模式,产生更加功能强大的匹配能力。比如,我们要匹配 1900年1月1日 到 2000年1月1日 除过闰年外的所有正确日期。

      我们先对这个匹配模式做一个分析:

      1. 首位可以是19也可以是20; Reg:19|20

      2. 当是19的时候,后面可以是00到99中任意数字; RegEx:19\d{2}|20

      3. 当是20的时候,只能匹配00; Reg:19\d{2}|2000

      4. 月份可以是1到9,或者10到12;Reg:(19\d{2}|2000)-([1-9]|1[0-2])

      因为天数与月份相关,所以将 ([1-9]|1[0-2]) 拆分为下面三个子模式:

      5. 当月份是2的时候,天数是28; Reg:2-([1-9]\b|1\d|2[0-8])

      6. 1、3、5、7、8、10、12月,天数是31; Reg:([13578]|1[02])-([1-9]\b|[12]\d|3[01])

      7. 4、6、9、11月,天数是30; Reg:([469]|11)-([1-9]\b|[12]\d|30)

      NOTE:注意上面日期部分的匹配,分成了两部分,月和日;对于月来说,如果我们要匹配大月(31天的月),写法是:[13578]|1[0-2];而日期部分,比如说要匹配31天,

    它又由三部分组成:[1-9]表示1号到9号;[12]\d表示10号到29号;3[01]表示30号到31号。

      还有个地方需要注意:单词边界问题,如果你这样写表达式:2-([1-9]|1\d|2[0-8]),对于2-29 这样不应该匹配的日期,会匹配它合法的部分 2-29,因为2-2满足2-[1-

    9]。回顾下我之前讲述的内容,我们还必须规定,当天数是个位数时,它必须处于单词边界[1-9]\b。

      组合一下,得到的月份和天数的模式是:

      2-([1-9]\b|1\d|2[0-8])|([13578]|1[02])-([1-9]\b|[12]\d|3[01])|([469]|11)-([1-9]\b|[12]\d|30)

      再结合上面年的部分,得到最终的结果:

      (19\d{2}|2000)-(2-([1-9]\b|1\d|2[0-8])|([13578]|1[02])-([1-9]\b|[12]\d|3[01])|([469]|11)-([1-9]\b|[12]\d|30))

    Text

      These dates are matched: 1900-1-1、1928-2-28、1931-11-30、2000-1-1、1999-10-30

      These dates are not matched: 1900-1-32、1928-2-29、2000-01-1、1982-12-08

    RegEx

      (19\d{2}|2000)-(2-([1-9]\b|1\d|2[0-8])|([13578]|1[02])-([1-9]\b|[12]\d|3[01])|([469]|11)-([1-9]\b|[12]\d|30))

    Result

      These dates are matched: 1900-1-11928-2-281931-11-302000-1-11999-10-30

      These dates are not matched: 1900-1-32、1928-2-29、2000-01-1、1982-12-08

    后向引用

     1.理解后向引用

      我们还是一如既往地从最简单的开始。假设我们要进行这样一个匹配:找出下面文本中所有重复的单词,以便日后进行替换。

      Is the cost of of gasline going up?

    我们看到:“of of”重复了,我们需要找出它:

    Text

      Is the cost of of gasline going up?

    RegEx

      of of

    Result

      Is the cost of of gasline going up?

      很显然,匹配结果满足了我们的要求,在这里使用全字匹配是为了后面好说明。

      现在,如果 up 也重复出现了,句子变成这样:

      Is the cost of of gasline going up up?

      我们就需要改写表达式成这样:

    Text

      Is the cost of of gasline going up up?

    RegEx

      (of|up) (of|up)

    Result

      Is the cost of of gasline going up up?

      NOTE:我们可以使用更简洁的表达式:((of|up)\b ??){2},但是为了后面好说明,这里我们还是使用全字匹配。

      关于这个表达式,首先记住,\b只是对边界进行限制,不匹配任何字符。

      如果写做((of|up)\b ){2},则无法匹配“up up”,因为它要求up后面必须出现一个空格“ ”,而本句中,up后面紧跟了一个问号;

      如果写成((of|up)\b ?){2},因为是贪婪匹配,如果of后出现空格,就会匹配之。两个of的匹配将变成“of of ”。通常,我们会替换它成一个“of”,这样,就会出现

    “ofgasline”的情况。

      最终,我们把贪婪匹配改成惰性匹配:((of|up)\b ??){2}

      可以看到,对这个句子来说,这样匹配没有问题。但是我们匹配的文本往往比这个复杂,让我们给上面的文本再添一句话。  

    Text

      Is the cost of of gasline going up up?

      Look up of the TV, your mobile phone is there.

    RegEx

      (of|up) (of|up)

    Result

      Is the cost of of gasline going up up?

      Look up of the TV, your mobile phone is there.

      不幸的是,对于下面不应该匹配的“up of”也进行了匹配。而我们需要的是这样一种匹配:当前面是“of”的时候,后面跟的也是“of”;当前面是“up”时,后面跟的也是

    “up”,只有这样的情况才去匹配它。换言之,后面所需要匹配的内容是前面的一个引用。

      正则表达式中,使用“\数字”来进行后向引用,数字表示这里引用的是前面的第几个子模式。

      我们回头在看本节第一个例子,我们也可以这样写:

    Text

      Is the cost of of gasline going up?

    RegEx

      (of) \1

    Result

      Is the cost of of gasline going up?

      这里,表达式“(of) \1”使用了后向引用,意思是:“\1”代表前面第一个匹配了的子模式的内容,对于本例,因为前面子模式只可能匹配“of”,那么“\1”等价于“of”,整个

    表达式相当于“of of”。

      现在,我们使用后向引用,对刚才出现“up of”问题的表达式加以纠正:

    Text

      Is the cost of of gasline going up up?

      Look up of the TV, your mobile phone is there.

    RegEx

      (of|up) \1

    Result

      Is the cost of of gasline going up up?

      Look up of the TV, your mobile phone is there.

      这一次,我们获得了预期的效果,“(of|up) \1”的含义是:如果前面 子模式1 匹配了“of”,那么“\1”就代表“of”;如果 子模式1 匹配了 “up”,那么“\1”就代表

    “up”,整个表达式相当于“of of|up up”。

  • 相关阅读:
    打造自定义 eslint
    二叉树(三): 二叉查找树
    二叉树(二): 补充
    二叉树(一): 遍历
    redux 源码浅析
    react-redux 源码浅析
    WebComponents使用以及思考
    SHELL 语法以及实例
    React-Native 原生 APP 更新
    关于 cdn 在项目中的使用
  • 原文地址:https://www.cnblogs.com/zuoguanglin/p/2430531.html
Copyright © 2011-2022 走看看