”、“
”、“
”全 部替换成一个“
”。按照之前的例子,我们只能写出这样的表达式: Text This is the first line.
This is the second line.
This is the third line.
>>>> RegEx
{2,} Result This is the first line.
This is the second line.
This is the third line.
>>>> 可以看到,匹配结果并不是我们想要的,这是因为 “{2,}”限制的是它之前的单个字符, 在本例中也就是“>”的出现次数,而我们希望的,是整个“
”、“
”或“
”。 1.子模式 在正则表达式中,可以使用“(”和“)”将模式中的子字符串括起来,以形成一个子模式。 将子模式视为一个整体时,那么它就相当于一个单个字符。 就本例而言,我们希望子模式就是 “
”,按上面的定义,我们重新写模式: Text Page 26 of 42 This is the first line.
This is the second line.
This is the third line.
>>>> RegEx (
){2,} Result This is the first line.
This is the second line.
This is the third line.
>>>> 这次匹配了正确的文本,我们可以将匹配过程理解成这样:子模式“(
)”首先匹 配所有“
”、“
”或“
”;然后,将每一个匹配结果视为一个整体(相当于单个 字符);接着,匹配这个整体连续出现两次或以上的文本。 2.“或”匹配 有的时候,我们要取消某段文字中的加粗、斜体等效果,我们想匹配所有的“”、“” 或者 “”、“”,然后把它们替换成空,仅利用之前的知识,我们只能进行两次匹配和 替换,一次是“?b>”,一次是“?i>”。 在正则表达式中,可以使用“|”将一个表达式拆分成两部分“reg1|reg2”,它的意思是: 匹配所有符合表达式 reg1 的文本 或者 符合表达式 reg2 的文本。 对于本节提出的问题,可以这样进行解决: Text The text of this row is bold. The text of this row is italic. RegEx ?i>|?b> Result The text of this row is bold. The text of this row is italic. 3.在子模式中使用“或”匹配 从上面的定义应该可以看出,“|”分隔的是整个表达式,而有的时候,我们希望分隔的是 一个表达式的一部分,比如说,我们想要匹配 “1900”到“2099”的所有年份。 Text Page 27 of 42 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 Page 28 of 42 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-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 后向引用 1.理解后向引用 我们还是一如既往地从最简单的开始。假设我们要进行这样一个匹配:找出下面文本中所有 重复的单词,以便日后进行替换。 Page 29 of 42 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? Page 30 of 42 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. Page 31 of 42 这一次,我们获得了预期的效果,“(of|up) \1”的含义是:如果前面 子模式 1 匹配了“of”, 那么“\1”就代表“of”;如果 子模式 1 匹配了 “up”,那么“\1”就代表“up”,整个表 达式相当于“of of|up up”。 在我们所讨论的简单情况下,已知的重复单词是确定的,我们可以找到后向引用的等价表达 式。但通常情况下,我们不知道哪些单词重复,这时候,就只能使用后向引用来完成: Text Is the cost of of gasline going up up? Look up of the TV, your mobile phone is there. You are the best of the the best. RegEx (\w+) \1 Result Is the cost of of gasline going up up? Look up of the TV, your mobile phone is there. You are the best of the the best. 这次,我想你应该可以想出“(\w+) \1”所代表的含义,就不再赘述了。 2.后向引用的一个常见应用 匹配重复单词是后向引用的一个较为常见的应用,还有一个应用是匹配有效的 HTML 标记: Text
This is a valid header
This is not valid. RegEx .*? Result This is a valid header
This is not valid. 可以看到,它只匹配了符合 HTML 语法的文本,对于前后不一致的文本没有进行匹配。 Page 32 of 42 3. .Net 中的后向引用 经常写正则表达式的朋友们应该都有体会:对于复杂的匹配,尤其是子模式嵌套子模式的情 况,常常判断不清楚后向引用匹配的到底是前面哪个子模式,比如:我们写的“\4”,期望它去 匹配第 4 个子模式,但往往它匹配了第 3 个或者第 5 个。 如果能有名字命名子模式就好了,这样,在后向引用中,我们可以使用这个名字,而不用根 据数字去判断。 在 .Net 中使用正则表达式进行查找时,给子模式命名的语法是:?,后向引用的语 法是:\k。 我们改写前面的范例: Text This is a valid header
This is not valid. RegEx [1-6])>.*? > Result This is a valid header
This is not valid. 可以看到,我们给子模式([1-6])起了个名字 sub,然后在后向引用中使用了它“\k”, “\k”就相当于“\1”。 文本替换 1.使用后向引用进行文本替换 迄今为止,我们所了解的正则表达式都是用于匹配文本,而如果我们对匹配了的文本不能进 行替代,那它也就没有什么用了。 所以,正则表达式的三部曲应该是:1、查找;2、引用匹配了的文本(后向引用);3、有选 择地替换文本。 需要注意的是:大部分语言的正则表达式实现,在查找中,使用后向引用来代表一个子模 式,其语法是“\数字”;而在替换中,其语法是“$数字”。 Page 33 of 42 1.1 高亮显示文本 假设我需要高亮显示所有 h1 中的文本,我们就可以使用后向引用来完成: Text This is a valid header
This is not valid. RegEx (.*?)
Replace $1
Result This is a valid header
This is not valid. 在这个例子中,“$1”代表了之间的文本。 1.2 替换电话号码格式 我们的电话格式通常都是:(区号)电话,比如说:(029)8401132;现在假设我们要求把文本 中所有的电话格式都改为:029-8401132,我们可以这样做: Text (020)82514769 (021)83281314 (029)88401132 RegEx \((\d{3})\)(\d{8}) Replace $1-$2 Result 020-82514769 021-83281314 029-88401132 如果这篇文章你是从头看到这里,相信这个表达式对你来说没有任何难度,需要留意的是这 里对元字符“(”和“)”进行了转义,并且,在替换结果中,我们要求它不出现。 Page 34 of 42 2. .Net 中的文本替换 同后向引用在查找时的情况类似,在 .Net 中,在替换时也可以对后向引用进行命名。 在 .Net 中使用正则表达式进行替换时,给子模式命名的语法是:?,后向引用的语 法是:${name}。 我们修改高亮显示 h1 文本的范例: Text This is a valid header
This is not valid. RegEx (?.*?)
Replace ${sub}
Result This is a valid header
This is not valid. 预查和非获取匹配 1.理解非获取匹配 假设我们有下面这样一段文本,而我们想要获取的 Windows 的所有版本,我们可以这样写: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows [\w.]+\b Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Page 35 of 42 Windows Vista is the Latest version of the family. 这时,如果我们想将所有的 Windows,全部换成简写 Win,并去掉 Windows 与 版本号 之 间的空格,我们则需要使用后向引用: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows ([\w.]+\b) Replace Win$1 Result Win1.03 and Win2.0 fisrt Released in 1985 and 1987 respectively. Win95 and Win98 are the successor. Then Win2000 and WinXp appeared. WinVista is the Latest version of the family. 我们首先查看一下表达式的区别,为了要使用后向引用,我们用“(”和“)”把“[\w.]+\b” 包起来,使它成为一个子模式。我们知道,只有这样,才可以用 $1 去引用它,这里,我们发现 使用子模式的一个作用:系统会在幕后将所有的子模式保存起来,以供后向引用使用(包含查找 时的后向引用 和 替换时的后向引用)。 而很多时候,我们添加一个子模式,并不是为了在后向引用中获取它,我们或许是出于匹配 需要,或许简单的只是为了使表达式更清晰。 正则表达式中,可以在子模式内部前面加“?:”来表示这个子模式是一个 非获取匹配,非 获取匹配不会被保存,不能在后向引用中获取。 对于本例,我们来测试一下: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows (?:[\w.]+\b) Page 36 of 42 Replace Win$1 Result Win$1 and Win$1 fisrt Released in 1985 and 1987 respectively. Win$1 and Win$1 are the successor. Then Win$1 and Win$1 appeared. Win$1 is the Latest version of the family. 我们看到,由于子模式没有被保存,所以“$1”被当作一个普通字符进行了处理。 而如果我们只是进行查找匹配,不进行替换,那么它们返回的效果相同: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows (?:[\w.]+\b) Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 可见,所谓 非获取匹配,意思就是说它只进行匹配,并不保存结果供以后引用。 2.正向预查 看到这里,你可能觉得 非获取匹配 没有什么实际用途。 现在,我们假设需要仅匹配 Windows,不匹配后面的版本号,并且要求 Windows 后面的版 本号只能是 数字类型,换言之,XP 和 Vista 不能被匹配,该如何做? 按照现有的知识,我们大概只能写出这样的表达式: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. Page 37 of 42 RegEx Windows [\d.]+\b Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 的确,它是匹配了 数字类型 版本的 Windows,但是,它不符合我们的要求。因为,我们要 求不能匹配版本号。 在正则表达式中,可以使用 正向预查 来解决这个问题。本例中,写法是:“Windows(?= [\d.]+\b)”。 它的语法是在 子模式内部 前面加“?=”,表示的意思是:首先,要匹配的文本必须满足 此子模式 前面 的表达式(本例,“Windows ”);其次,此子模式不参与匹配。 Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows( ?=[\d.]+\b) Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 这次,你大概了解了 “非获取匹配” 这五个汉字的含义,它们仅仅起一个限制作用,不参 与匹配。你可以将 正向预查 理解成为自定义的边界(\b),这个边界位于 表达式末。 反言之,你可以将位于表达式末的 \b 理解成非获取匹配的一个特例:(?=[ ,.\r\n<>;\-])。 注意,这里我没有写全边界符号。 Text aaaax-aaa aaaaxaaaa RegEx x(?=[,.\r\n<>;\-]) Page 38 of 42 Result aaaax-aaa aaaaxaaaa 你也可以这样理解上面的匹配过程: 1. 先进行普通匹配:Windows ([\d.]+\b) 2. 然后从匹配文本中将 子模式 内的文本排除掉。 3.反向预查 在上面的例子中,我们知道 正向预查 类似于自定义的 位于文本末 的字符边界。那么自然 应该有位于文本首的情况,比如说,我们要匹配下面文本中属于 CNY 的金额: Text CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 RegEx CNY: \d+\.\d+ Result CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 与上面类似,我们现在要求仅匹配金额,而不匹配前面的 “CNY:” 正则表达式中,可以使用 反向预查 来解决这个问题。本例中,写法是:(?<=CNY: )\d+\.\d+ 反向预查 的语法是在子模式内部前面加“?<=”,表示的意思是:首先,要匹配的文本必 须满足此子模式 后面 的表达式(本例,“\d+.\d+”);其次,此子模式不参与匹配。 Text CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 Page 39 of 42 RegEx (?<=CNY: )\d+\.\d+ Result CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 与前面类似:你可以将 反向预查 理解成为自定义的边界(\b),这个边界位于 表达式首。 反言之,你可以将位于 表达式首 的 \b 理解成一个非获取匹配的一个特例: (?<=[ ,.\r\n<>;\-])。注意,我没有写全所有边界。 Text aaa-xaaaa aaaxaaaaa RegEx (?<=[,.\r\n<>;\-])x Result aaa-xaaaa aaaxaaaaa 你也可以这样理解上面的匹配过程: 1. 先进行普通匹配:(CNY: )\d+\.\d+ 2. 然后从匹配文本中将 子模式 内的文本排除掉。 4.正向、反向预查组合 我们可以将正向预查 和 反向预查 组合起来使用,比如我们想获取所有 head 之间的文本, 就可以这么写: Text This is header.
This is header,too.
This is not a header. RegEx (?<=[1-6])>).*?(?= >) Page 40 of 42 Result This is header.
This is header,too.
This is not a header. 注意,这里我综合应用了前面的知识,将首尾不一致的“
”做了过滤。 5.负正向预查、负反向预查 5.1 负正向预查 如同 \b 有与之相对的 \B 一样,正向预查 也有它的 逆过程,称之为 负正向预查。 在正则表达式中,可以在子模式内部前面加 “?!” 来形成一个 负正向预查,它的效果与 “?=” 相反。 Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows(?! [\d.]+\b) Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 从结果我们看到,它匹配了后面不是数字版本的 Windows。 5.2 负反向预查 在正则表达式中,可以在子模式内部前面加 “?
...
还剩44页未读
继续阅读
This is a valid header
This is not valid. RegEx [1-6])>.*? > Result This is a valid header
This is not valid. 可以看到,我们给子模式([1-6])起了个名字 sub,然后在后向引用中使用了它“\k”, “\k”就相当于“\1”。 文本替换 1.使用后向引用进行文本替换 迄今为止,我们所了解的正则表达式都是用于匹配文本,而如果我们对匹配了的文本不能进 行替代,那它也就没有什么用了。 所以,正则表达式的三部曲应该是:1、查找;2、引用匹配了的文本(后向引用);3、有选 择地替换文本。 需要注意的是:大部分语言的正则表达式实现,在查找中,使用后向引用来代表一个子模 式,其语法是“\数字”;而在替换中,其语法是“$数字”。 Page 33 of 42 1.1 高亮显示文本 假设我需要高亮显示所有 h1 中的文本,我们就可以使用后向引用来完成: Text This is a valid header
This is not valid. RegEx (.*?)
Replace $1
Result This is a valid header
This is not valid. 在这个例子中,“$1”代表了之间的文本。 1.2 替换电话号码格式 我们的电话格式通常都是:(区号)电话,比如说:(029)8401132;现在假设我们要求把文本 中所有的电话格式都改为:029-8401132,我们可以这样做: Text (020)82514769 (021)83281314 (029)88401132 RegEx \((\d{3})\)(\d{8}) Replace $1-$2 Result 020-82514769 021-83281314 029-88401132 如果这篇文章你是从头看到这里,相信这个表达式对你来说没有任何难度,需要留意的是这 里对元字符“(”和“)”进行了转义,并且,在替换结果中,我们要求它不出现。 Page 34 of 42 2. .Net 中的文本替换 同后向引用在查找时的情况类似,在 .Net 中,在替换时也可以对后向引用进行命名。 在 .Net 中使用正则表达式进行替换时,给子模式命名的语法是:?,后向引用的语 法是:${name}。 我们修改高亮显示 h1 文本的范例: Text This is a valid header
This is not valid. RegEx (?.*?)
Replace ${sub}
Result This is a valid header
This is not valid. 预查和非获取匹配 1.理解非获取匹配 假设我们有下面这样一段文本,而我们想要获取的 Windows 的所有版本,我们可以这样写: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows [\w.]+\b Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Page 35 of 42 Windows Vista is the Latest version of the family. 这时,如果我们想将所有的 Windows,全部换成简写 Win,并去掉 Windows 与 版本号 之 间的空格,我们则需要使用后向引用: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows ([\w.]+\b) Replace Win$1 Result Win1.03 and Win2.0 fisrt Released in 1985 and 1987 respectively. Win95 and Win98 are the successor. Then Win2000 and WinXp appeared. WinVista is the Latest version of the family. 我们首先查看一下表达式的区别,为了要使用后向引用,我们用“(”和“)”把“[\w.]+\b” 包起来,使它成为一个子模式。我们知道,只有这样,才可以用 $1 去引用它,这里,我们发现 使用子模式的一个作用:系统会在幕后将所有的子模式保存起来,以供后向引用使用(包含查找 时的后向引用 和 替换时的后向引用)。 而很多时候,我们添加一个子模式,并不是为了在后向引用中获取它,我们或许是出于匹配 需要,或许简单的只是为了使表达式更清晰。 正则表达式中,可以在子模式内部前面加“?:”来表示这个子模式是一个 非获取匹配,非 获取匹配不会被保存,不能在后向引用中获取。 对于本例,我们来测试一下: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows (?:[\w.]+\b) Page 36 of 42 Replace Win$1 Result Win$1 and Win$1 fisrt Released in 1985 and 1987 respectively. Win$1 and Win$1 are the successor. Then Win$1 and Win$1 appeared. Win$1 is the Latest version of the family. 我们看到,由于子模式没有被保存,所以“$1”被当作一个普通字符进行了处理。 而如果我们只是进行查找匹配,不进行替换,那么它们返回的效果相同: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows (?:[\w.]+\b) Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 可见,所谓 非获取匹配,意思就是说它只进行匹配,并不保存结果供以后引用。 2.正向预查 看到这里,你可能觉得 非获取匹配 没有什么实际用途。 现在,我们假设需要仅匹配 Windows,不匹配后面的版本号,并且要求 Windows 后面的版 本号只能是 数字类型,换言之,XP 和 Vista 不能被匹配,该如何做? 按照现有的知识,我们大概只能写出这样的表达式: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. Page 37 of 42 RegEx Windows [\d.]+\b Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 的确,它是匹配了 数字类型 版本的 Windows,但是,它不符合我们的要求。因为,我们要 求不能匹配版本号。 在正则表达式中,可以使用 正向预查 来解决这个问题。本例中,写法是:“Windows(?= [\d.]+\b)”。 它的语法是在 子模式内部 前面加“?=”,表示的意思是:首先,要匹配的文本必须满足 此子模式 前面 的表达式(本例,“Windows ”);其次,此子模式不参与匹配。 Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows( ?=[\d.]+\b) Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 这次,你大概了解了 “非获取匹配” 这五个汉字的含义,它们仅仅起一个限制作用,不参 与匹配。你可以将 正向预查 理解成为自定义的边界(\b),这个边界位于 表达式末。 反言之,你可以将位于表达式末的 \b 理解成非获取匹配的一个特例:(?=[ ,.\r\n<>;\-])。 注意,这里我没有写全边界符号。 Text aaaax-aaa aaaaxaaaa RegEx x(?=[,.\r\n<>;\-]) Page 38 of 42 Result aaaax-aaa aaaaxaaaa 你也可以这样理解上面的匹配过程: 1. 先进行普通匹配:Windows ([\d.]+\b) 2. 然后从匹配文本中将 子模式 内的文本排除掉。 3.反向预查 在上面的例子中,我们知道 正向预查 类似于自定义的 位于文本末 的字符边界。那么自然 应该有位于文本首的情况,比如说,我们要匹配下面文本中属于 CNY 的金额: Text CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 RegEx CNY: \d+\.\d+ Result CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 与上面类似,我们现在要求仅匹配金额,而不匹配前面的 “CNY:” 正则表达式中,可以使用 反向预查 来解决这个问题。本例中,写法是:(?<=CNY: )\d+\.\d+ 反向预查 的语法是在子模式内部前面加“?<=”,表示的意思是:首先,要匹配的文本必 须满足此子模式 后面 的表达式(本例,“\d+.\d+”);其次,此子模式不参与匹配。 Text CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 Page 39 of 42 RegEx (?<=CNY: )\d+\.\d+ Result CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 与前面类似:你可以将 反向预查 理解成为自定义的边界(\b),这个边界位于 表达式首。 反言之,你可以将位于 表达式首 的 \b 理解成一个非获取匹配的一个特例: (?<=[ ,.\r\n<>;\-])。注意,我没有写全所有边界。 Text aaa-xaaaa aaaxaaaaa RegEx (?<=[,.\r\n<>;\-])x Result aaa-xaaaa aaaxaaaaa 你也可以这样理解上面的匹配过程: 1. 先进行普通匹配:(CNY: )\d+\.\d+ 2. 然后从匹配文本中将 子模式 内的文本排除掉。 4.正向、反向预查组合 我们可以将正向预查 和 反向预查 组合起来使用,比如我们想获取所有 head 之间的文本, 就可以这么写: Text This is header.
This is header,too.
This is not a header. RegEx (?<=[1-6])>).*?(?= >) Page 40 of 42 Result This is header.
This is header,too.
This is not a header. 注意,这里我综合应用了前面的知识,将首尾不一致的“
”做了过滤。 5.负正向预查、负反向预查 5.1 负正向预查 如同 \b 有与之相对的 \B 一样,正向预查 也有它的 逆过程,称之为 负正向预查。 在正则表达式中,可以在子模式内部前面加 “?!” 来形成一个 负正向预查,它的效果与 “?=” 相反。 Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows(?! [\d.]+\b) Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 从结果我们看到,它匹配了后面不是数字版本的 Windows。 5.2 负反向预查 在正则表达式中,可以在子模式内部前面加 “?
...
还剩44页未读
继续阅读
This is a valid header
This is not valid. RegEx (.*?)
Replace $1
Result This is a valid header
This is not valid. 在这个例子中,“$1”代表了之间的文本。 1.2 替换电话号码格式 我们的电话格式通常都是:(区号)电话,比如说:(029)8401132;现在假设我们要求把文本 中所有的电话格式都改为:029-8401132,我们可以这样做: Text (020)82514769 (021)83281314 (029)88401132 RegEx \((\d{3})\)(\d{8}) Replace $1-$2 Result 020-82514769 021-83281314 029-88401132 如果这篇文章你是从头看到这里,相信这个表达式对你来说没有任何难度,需要留意的是这 里对元字符“(”和“)”进行了转义,并且,在替换结果中,我们要求它不出现。 Page 34 of 42 2. .Net 中的文本替换 同后向引用在查找时的情况类似,在 .Net 中,在替换时也可以对后向引用进行命名。 在 .Net 中使用正则表达式进行替换时,给子模式命名的语法是:?,后向引用的语 法是:${name}。 我们修改高亮显示 h1 文本的范例: Text This is a valid header
This is not valid. RegEx (?.*?)
Replace ${sub}
Result This is a valid header
This is not valid. 预查和非获取匹配 1.理解非获取匹配 假设我们有下面这样一段文本,而我们想要获取的 Windows 的所有版本,我们可以这样写: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows [\w.]+\b Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Page 35 of 42 Windows Vista is the Latest version of the family. 这时,如果我们想将所有的 Windows,全部换成简写 Win,并去掉 Windows 与 版本号 之 间的空格,我们则需要使用后向引用: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows ([\w.]+\b) Replace Win$1 Result Win1.03 and Win2.0 fisrt Released in 1985 and 1987 respectively. Win95 and Win98 are the successor. Then Win2000 and WinXp appeared. WinVista is the Latest version of the family. 我们首先查看一下表达式的区别,为了要使用后向引用,我们用“(”和“)”把“[\w.]+\b” 包起来,使它成为一个子模式。我们知道,只有这样,才可以用 $1 去引用它,这里,我们发现 使用子模式的一个作用:系统会在幕后将所有的子模式保存起来,以供后向引用使用(包含查找 时的后向引用 和 替换时的后向引用)。 而很多时候,我们添加一个子模式,并不是为了在后向引用中获取它,我们或许是出于匹配 需要,或许简单的只是为了使表达式更清晰。 正则表达式中,可以在子模式内部前面加“?:”来表示这个子模式是一个 非获取匹配,非 获取匹配不会被保存,不能在后向引用中获取。 对于本例,我们来测试一下: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows (?:[\w.]+\b) Page 36 of 42 Replace Win$1 Result Win$1 and Win$1 fisrt Released in 1985 and 1987 respectively. Win$1 and Win$1 are the successor. Then Win$1 and Win$1 appeared. Win$1 is the Latest version of the family. 我们看到,由于子模式没有被保存,所以“$1”被当作一个普通字符进行了处理。 而如果我们只是进行查找匹配,不进行替换,那么它们返回的效果相同: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows (?:[\w.]+\b) Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 可见,所谓 非获取匹配,意思就是说它只进行匹配,并不保存结果供以后引用。 2.正向预查 看到这里,你可能觉得 非获取匹配 没有什么实际用途。 现在,我们假设需要仅匹配 Windows,不匹配后面的版本号,并且要求 Windows 后面的版 本号只能是 数字类型,换言之,XP 和 Vista 不能被匹配,该如何做? 按照现有的知识,我们大概只能写出这样的表达式: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. Page 37 of 42 RegEx Windows [\d.]+\b Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 的确,它是匹配了 数字类型 版本的 Windows,但是,它不符合我们的要求。因为,我们要 求不能匹配版本号。 在正则表达式中,可以使用 正向预查 来解决这个问题。本例中,写法是:“Windows(?= [\d.]+\b)”。 它的语法是在 子模式内部 前面加“?=”,表示的意思是:首先,要匹配的文本必须满足 此子模式 前面 的表达式(本例,“Windows ”);其次,此子模式不参与匹配。 Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows( ?=[\d.]+\b) Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 这次,你大概了解了 “非获取匹配” 这五个汉字的含义,它们仅仅起一个限制作用,不参 与匹配。你可以将 正向预查 理解成为自定义的边界(\b),这个边界位于 表达式末。 反言之,你可以将位于表达式末的 \b 理解成非获取匹配的一个特例:(?=[ ,.\r\n<>;\-])。 注意,这里我没有写全边界符号。 Text aaaax-aaa aaaaxaaaa RegEx x(?=[,.\r\n<>;\-]) Page 38 of 42 Result aaaax-aaa aaaaxaaaa 你也可以这样理解上面的匹配过程: 1. 先进行普通匹配:Windows ([\d.]+\b) 2. 然后从匹配文本中将 子模式 内的文本排除掉。 3.反向预查 在上面的例子中,我们知道 正向预查 类似于自定义的 位于文本末 的字符边界。那么自然 应该有位于文本首的情况,比如说,我们要匹配下面文本中属于 CNY 的金额: Text CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 RegEx CNY: \d+\.\d+ Result CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 与上面类似,我们现在要求仅匹配金额,而不匹配前面的 “CNY:” 正则表达式中,可以使用 反向预查 来解决这个问题。本例中,写法是:(?<=CNY: )\d+\.\d+ 反向预查 的语法是在子模式内部前面加“?<=”,表示的意思是:首先,要匹配的文本必 须满足此子模式 后面 的表达式(本例,“\d+.\d+”);其次,此子模式不参与匹配。 Text CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 Page 39 of 42 RegEx (?<=CNY: )\d+\.\d+ Result CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 与前面类似:你可以将 反向预查 理解成为自定义的边界(\b),这个边界位于 表达式首。 反言之,你可以将位于 表达式首 的 \b 理解成一个非获取匹配的一个特例: (?<=[ ,.\r\n<>;\-])。注意,我没有写全所有边界。 Text aaa-xaaaa aaaxaaaaa RegEx (?<=[,.\r\n<>;\-])x Result aaa-xaaaa aaaxaaaaa 你也可以这样理解上面的匹配过程: 1. 先进行普通匹配:(CNY: )\d+\.\d+ 2. 然后从匹配文本中将 子模式 内的文本排除掉。 4.正向、反向预查组合 我们可以将正向预查 和 反向预查 组合起来使用,比如我们想获取所有 head 之间的文本, 就可以这么写: Text This is header.
This is header,too.
This is not a header. RegEx (?<=[1-6])>).*?(?= >) Page 40 of 42 Result This is header.
This is header,too.
This is not a header. 注意,这里我综合应用了前面的知识,将首尾不一致的“
”做了过滤。 5.负正向预查、负反向预查 5.1 负正向预查 如同 \b 有与之相对的 \B 一样,正向预查 也有它的 逆过程,称之为 负正向预查。 在正则表达式中,可以在子模式内部前面加 “?!” 来形成一个 负正向预查,它的效果与 “?=” 相反。 Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows(?! [\d.]+\b) Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 从结果我们看到,它匹配了后面不是数字版本的 Windows。 5.2 负反向预查 在正则表达式中,可以在子模式内部前面加 “?
...
还剩44页未读
继续阅读
This is a valid header
This is not valid. RegEx (?.*?)
Replace ${sub}
Result This is a valid header
This is not valid. 预查和非获取匹配 1.理解非获取匹配 假设我们有下面这样一段文本,而我们想要获取的 Windows 的所有版本,我们可以这样写: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows [\w.]+\b Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Page 35 of 42 Windows Vista is the Latest version of the family. 这时,如果我们想将所有的 Windows,全部换成简写 Win,并去掉 Windows 与 版本号 之 间的空格,我们则需要使用后向引用: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows ([\w.]+\b) Replace Win$1 Result Win1.03 and Win2.0 fisrt Released in 1985 and 1987 respectively. Win95 and Win98 are the successor. Then Win2000 and WinXp appeared. WinVista is the Latest version of the family. 我们首先查看一下表达式的区别,为了要使用后向引用,我们用“(”和“)”把“[\w.]+\b” 包起来,使它成为一个子模式。我们知道,只有这样,才可以用 $1 去引用它,这里,我们发现 使用子模式的一个作用:系统会在幕后将所有的子模式保存起来,以供后向引用使用(包含查找 时的后向引用 和 替换时的后向引用)。 而很多时候,我们添加一个子模式,并不是为了在后向引用中获取它,我们或许是出于匹配 需要,或许简单的只是为了使表达式更清晰。 正则表达式中,可以在子模式内部前面加“?:”来表示这个子模式是一个 非获取匹配,非 获取匹配不会被保存,不能在后向引用中获取。 对于本例,我们来测试一下: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows (?:[\w.]+\b) Page 36 of 42 Replace Win$1 Result Win$1 and Win$1 fisrt Released in 1985 and 1987 respectively. Win$1 and Win$1 are the successor. Then Win$1 and Win$1 appeared. Win$1 is the Latest version of the family. 我们看到,由于子模式没有被保存,所以“$1”被当作一个普通字符进行了处理。 而如果我们只是进行查找匹配,不进行替换,那么它们返回的效果相同: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows (?:[\w.]+\b) Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 可见,所谓 非获取匹配,意思就是说它只进行匹配,并不保存结果供以后引用。 2.正向预查 看到这里,你可能觉得 非获取匹配 没有什么实际用途。 现在,我们假设需要仅匹配 Windows,不匹配后面的版本号,并且要求 Windows 后面的版 本号只能是 数字类型,换言之,XP 和 Vista 不能被匹配,该如何做? 按照现有的知识,我们大概只能写出这样的表达式: Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. Page 37 of 42 RegEx Windows [\d.]+\b Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 的确,它是匹配了 数字类型 版本的 Windows,但是,它不符合我们的要求。因为,我们要 求不能匹配版本号。 在正则表达式中,可以使用 正向预查 来解决这个问题。本例中,写法是:“Windows(?= [\d.]+\b)”。 它的语法是在 子模式内部 前面加“?=”,表示的意思是:首先,要匹配的文本必须满足 此子模式 前面 的表达式(本例,“Windows ”);其次,此子模式不参与匹配。 Text Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. RegEx Windows( ?=[\d.]+\b) Result Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively. Windows 95 and Windows 98 are the successor. Then Windows 2000 and Windows Xp appeared. Windows Vista is the Latest version of the family. 这次,你大概了解了 “非获取匹配” 这五个汉字的含义,它们仅仅起一个限制作用,不参 与匹配。你可以将 正向预查 理解成为自定义的边界(\b),这个边界位于 表达式末。 反言之,你可以将位于表达式末的 \b 理解成非获取匹配的一个特例:(?=[ ,.\r\n<>;\-])。 注意,这里我没有写全边界符号。 Text aaaax-aaa aaaaxaaaa RegEx x(?=[,.\r\n<>;\-]) Page 38 of 42 Result aaaax-aaa aaaaxaaaa 你也可以这样理解上面的匹配过程: 1. 先进行普通匹配:Windows ([\d.]+\b) 2. 然后从匹配文本中将 子模式 内的文本排除掉。 3.反向预查 在上面的例子中,我们知道 正向预查 类似于自定义的 位于文本末 的字符边界。那么自然 应该有位于文本首的情况,比如说,我们要匹配下面文本中属于 CNY 的金额: Text CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 RegEx CNY: \d+\.\d+ Result CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 与上面类似,我们现在要求仅匹配金额,而不匹配前面的 “CNY:” 正则表达式中,可以使用 反向预查 来解决这个问题。本例中,写法是:(?<=CNY: )\d+\.\d+ 反向预查 的语法是在子模式内部前面加“?<=”,表示的意思是:首先,要匹配的文本必 须满足此子模式 后面 的表达式(本例,“\d+.\d+”);其次,此子模式不参与匹配。 Text CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 Page 39 of 42 RegEx (?<=CNY: )\d+\.\d+ Result CNY: 128.04 USD: 22.5 USD: 23.5 HKD: 1533.5 CNY: 23.78 与前面类似:你可以将 反向预查 理解成为自定义的边界(\b),这个边界位于 表达式首。 反言之,你可以将位于 表达式首 的 \b 理解成一个非获取匹配的一个特例: (?<=[ ,.\r\n<>;\-])。注意,我没有写全所有边界。 Text aaa-xaaaa aaaxaaaaa RegEx (?<=[,.\r\n<>;\-])x Result aaa-xaaaa aaaxaaaaa 你也可以这样理解上面的匹配过程: 1. 先进行普通匹配:(CNY: )\d+\.\d+ 2. 然后从匹配文本中将 子模式 内的文本排除掉。 4.正向、反向预查组合 我们可以将正向预查 和 反向预查 组合起来使用,比如我们想获取所有 head 之间的文本, 就可以这么写: Text This is header.
This is header,too.
This is not a header. RegEx (?<=[1-6])>).*?(?= >) Page 40 of 42 Result This is header.
This is header.
This is header,too.
This is not a header. 注意,这里我综合应用了前面的知识,将首尾不一致的“
还剩44页未读
继续阅读