Andy Niu Help
1.0.0.0
|
模块 | |
常用正则表达式 | |
变量 | |
特殊字符和转义 | |
匹配优先和忽略优先 | |
括号的用处 | |
环视 | |
分组_捕获_反向引用 | |
分组_不捕获 | |
固化分组 | |
占有优先 | |
详细描述
变量说明
分组_不捕获 |
1、在分组_捕获_反向引用一节中,我们对每个分组都进行了捕获,比如查找重复出现的[a-zA-Z]+\d, 使用([a-zA-Z]+)(\d)(\1)(\2),(\1)(\2) 我们不需要使用,也进行了捕获,也就是说正则表达式 引擎必须记住(\1)(\2)的内容,这会导致额外的开销。 2、怎么解决? 解决办法是使用分组不捕获,如下: ([a-zA-Z]+)(\d)\1\2 注意:这个时候使用notepad++进行替换的时候,只捕获了两个分组,$1对应([a-zA-Z]+),$2对应(\d) 没有$3和$4,也可认为$3和$4对应为空。 3、考虑下面的需求,找出[a-zA-Z]+\d[a-zA-Z]+,其中[a-zA-Z]+相同,也就是说\d不需要捕获,使用分组不捕获,如下: ([a-zA-Z]+)(?:\d)\1 4、在notepad++,匹配的时候使用\n反向引用第n个捕获到的分组,替换的时候使用$n替换第n个捕获到的分组, 有些程序支持命名捕获分组,对捕获到的分组,取一个名字,后面根据名称引用。 5、注意:\d等价于[0-9],还有一个常用的缩写\w,但是不推荐使用\w,因为不同的程序对\w的解释不同, 有些等价于[a-zA-Z0-9],有些等价于[a-zA-Z0-9_],有些等价于所有的显示字符,包括等号减号等, 为了兼容,不推荐使用\w
分组_捕获_反向引用 |
1、考虑下面的需求,对于文本 Andy1Andy1 Bill3Bill4 Caroine5Caroine5 找出重复出现的[a-zA-Z]+\d,也就是说Andy1Andy1匹配成功,Bill3Bill4匹配失败。 2、使用分组_捕获_反向引用,如下: ([a-zA-Z]+)(\d)(\1)(\2) (\1)反向引用([a-zA-Z]+),然后本身又作为一个捕获分组。 3、这里捕获了4个分组,使用notepad++进行替换的时候,$1对应([a-zA-Z]+),$2对应(\d), $3对应(\1),$4对应(\2) 4、考虑下面的需求,找出连续出现3次[a-zA-Z]+\d的文本,如下: ([a-zA-Z]+)(\d)(\1)(\2)(\1)(\2),当然也可以使用 ([a-zA-Z]+)(\d)(\1)(\2)(\3)(\4)
- 参见
- 分组_不捕获
匹配优先和忽略优先 |
1、考虑下面的需求,"Tom" is short for "Thomas" 找出所有的双引号括住的内容。以notepad++为例说明。 2、容易想到的办法:查找 ".*" 发现找出的结果是 "Tom" is short for "Thomas" 3、这不是我们所期望的,为什么? 因为.* 是匹配优先,即贪婪模式,也就是说会尽量多吃。 4、怎么解决这个问题? 使用忽略优先,也就是尽量少吃,如下:".*?" 对于不支持忽略优先的程序,可以使用"[^"]*" ,实现忽略优先。 "[^"]*" 表示可以尽量多吃,但是不能吃",遇到第一个"就要停下来。
- 参见
占有优先 |
1、占有优先和固化分组一样,解决同样的问题,吃下去,丢弃备用状态,以后不会吐出来。 2、占有优先的语法如下: ([a-zA-Z]++):
- 参见
固化分组 |
1、考虑下面的需求,使用[a-zA-Z]+: 去匹配文本,对于文本Subject,分析匹配过程。 2、[a-zA-Z]+匹配优先,一直吃到t,发现冒号不能匹配,于是使用备用状态,吐出一个字符, 还是不能匹配,再吐出一个字符......一直继续下去。 3、这里存在问题,引擎试图吐出一个字符匹配冒号,我们知道这是徒劳的尝试。因为[a-zA-Z]+没有吃下去冒号,当然不可能吐出冒号。 如果正则表达式引擎足够聪明,意识到这一点,就不需要尝试吐出字符,直接报告匹配失败,也就是说,之前的备用状态应该丢弃。 但是,一般情况下,引擎没有这么聪明,需要人为的协助,提示引擎不需要吐出字符,也就是丢弃之前的备用状态。 4、怎么提示引擎呢? 使用固化分组,如下 (?>[a-zA-Z]+): (?>[a-zA-Z]+)作为一个整体,吃下去文本,即使后面匹配失败,也不吐出来。 5、也就是说,使用固化分组可以提前报告匹配失败,不需要进行徒劳的尝试,提高效率。 6、对于不支持固化分组的程序,可以使用占有优先和环视。 占有优先,如下 ([a-zA-Z]++): 环视匹配一个位置,有一个重要的特点,就是匹配尝试结束后,不会留下任何备用状态,因此,使用环视解决上面的问题,如下: (?=([a-zA-Z]+))\1: (?=([a-zA-Z]+))匹配一个位置,右边是([a-zA-Z]+),\1反向引用([a-zA-Z]+),后面跟着一个冒号。
- 参见
括号的用处 |
1、限定多选项的范围 gr(a|e)y,查找 gray和grey,等价于gr[ae]y 2、多个字符括住,合成一个单元,接受量词的限制 (th){2},查找th出现量词 3、分组,反向引用 表达式:([a-z]{3})([0-9]{2})\1\2 ,匹配下列文本, abc12def12 // 匹配失败 thy34thy34 // 匹配成功 4、环视功能 (?=\d) 顺序环视(右边包含一个数字) (?<=\d) 逆序环视(左边包含一个数字) =换成! 变成否定环视,左边或右边不包含一个数字。
- 参见
特殊字符和转义 |
1、正则表达式中有些字符用作特殊的意义,比如元字符* 表示匹配0个或多个,小括号() 表示分组。 2、这些字符表示特殊的意义,如何表示这些字符本身呢?使用转义字符\,告诉程序右斜杠后面的字符 是字符本身。比如: shell中,双引号用作框住字符串,要表示双引号本身,需要转义,echo "\"Hello\"" 特别注意:不同程序,所包含的特殊字符不一样。同时是否转义的说明也不同,比如: 在notepad++中,+ 表示匹配1个或多个,\+ 表示+字符本身 在vim中,+ 就是+字符本身,\+匹配一个或多个
- 参见
环视 |
1、环视就是看周围的意思,环视匹配一个位置,这个位置的周围满足一些条件。 也就是这个位置的左右,包含某些内容,或者不包含某些内容。 2、考虑下面的需求,对于12,345,678,修改为 12,345,678。 这个需求要做的事情就是在数字中的一些位置添加逗号,这个位置的特点是: 前面匹配一个数字,后面匹配三个数字的整数倍,结尾不是数字或者是换行符。 3、解决办法: 查找 (?<=\d)(?=(\d\d\d)+([^\d]|$)) 替换为逗号。也就是查找一个位置,替换为逗号。 4、匹配流程如下: 先匹配1,后面有7个数字,不是3的倍数,匹配失败。 再匹配2,后面有6个数字,是3的倍数,匹配成功,替换。 再匹配3,后面有5个数字,是3的倍数,匹配失败。 ...... 5、环视还有一个重要的特点,就是匹配尝试结束后,不会留下任何备用状态,利用这一点可以解决固化分组的问题。
- 参见
- 固化分组
Copyright (c) 2015~2016, Andy Niu @All rights reserved. By Andy Niu Edit.