捕获组
语法:
字符 | 描述 | 示例 |
(pattern) | 匹配pattern并捕获结果,自动设置组号。 | (abc)+d 匹配abcd或者abcabcd |
(?<name>pattern) 或 (?'name'pattern) | 匹配pattern并捕获结果,设置name为组名。 |
|
\num | 对捕获组的反向引用。其中 num 是一个正整数。 | (\w)(\w)\2\1 匹配abba |
\k< name > 或 \k' name ' | 对命名捕获组的反向引用。其中 name 是捕获组名。 | (?<group>\w)abc\k<group> 匹配xabcx |
例如:
(\d{4})-(\d{2}-(\d{2}))
1 1 2 3 32
也可以自己指定子表达式的组名。这样在表达式或程序中可以直接引用组名,当然也可以继续使用组号。但如果正则表达式中同时存在普通捕获组和命名捕获组,那么捕获组的编号就要特别注意,编号的规则是先对普通捕获组进行编号,再对命名捕获组进行编号。
例如:
(\d{4})-(?<date>\d{2}-(\d{2}))
1 1 3 2 23
非捕获组
语法:
字符 | 描述 | 示例 |
(?:pattern) | 匹配pattern,但不捕获匹配结果。 | 'industr(?:y|ies)' 匹配'industry'或'industries'。 |
(?=pattern) | 零宽度正向预查,不捕获匹配结果。 | '^(?:[1-9](?=[4-6])\d(?=[7-9])\d)$' 匹配 数字为: 147 即为第二个数字的范围为[4-6] 第三个数字的范围为[7-9] 不匹配 129 |
(?!pattern) | 零宽度负向预查,不捕获匹配结果。 | '^(?:[1-9](?![4-6])\d(?![7-9])\d)$' 匹配 数字为:129 即 第二个数字的范围为[0-3]或者[7-9] 第三个数字的范围 [0-6] 不匹配 数字为 147 |
(?<=pattern) | 零宽度正向回查,不捕获匹配结果。 | '^\d{1,2}(?<=[3-9][7-9])$' 匹配 数字范围 >36 |
(?<!pattern) | 零宽度负向回查,不捕获匹配结果。 |
'^\d{1,2}(?<!3[7-9])\d?(?<!36[1-9])$' 匹配 数字范围 为[0-360] '^\d{1,2}(?<!3[7-9])$' 匹配 数字范围 <=36 |
非捕获组只匹配结果,但不捕获结果,也不会分配组号,当然也不能在表达式和程序中做进一步处理。
首先(?:pattern)与(pattern)不同之处只是在于不捕获结果。
接下来的四个非捕获组用于匹配pattern(或者不匹配pattern)位置之前(或之后)的内容。匹配的结果不包括pattern。
例如:
(?<=<(\w+)>).*(?=<\/\1>)匹配不包含属性的简单HTML标签内的内容。如:<div>hello</div>之中的hello,匹配结果不包括前缀<div>和后缀</div>。
注释
语法:
字符 | 描述 | 示例 |
(?#comment) | comment是注释,不对正则表达式的处理产生任何影响 | 2[0-4]\d(?#200-249)|25[0-5](?#250-255)|1?\d\d?(?#0-199) 匹配0-255的整数 |
这个不解释了。
匹配优先模式:通常, *, ?, +, 和 {min,max}是匹配优先量词因为他们都是尽可能多地去匹配字符。
Hsuda:这里插播一个例子,对于匹配优先模式,我们将遇到一个很常见的陷阱。比如,我们要搜索的句子是
They call me "Hsudatalks" or "Freedom".
我希望搜索第一对引号里的内容,可能会产生这样的表达式".+",可是由于*是匹配优先的量词,我们得到的结果是
"Hsudatalks" or "Freedom"
这明显不是我们所期望的结果。那该怎么办呢?请看下面的帮助:
在他们后面使用问号则可以让他们尽可能少的匹配字符。那上面的例子我们采用".+?",所得到的便是"Hsudatalks"。
例:表达式<.+>所表示的意思是先搜索<,在匹配一个或者更多的任意字符,后面跟着一个>。在匹配时会出现 <em>text</em>,为了避免这种情况,我们使用<.+?> 使得表达式仅仅只会匹配标记<em>。
顺序环视和逆序环视: (?=...),(?!...),(?<=...) 和 (?<!...) 被成为环视,因为他们都是形容一个匹配条件而不消耗任何字符。比如:abc(?=.*xyz) 匹配右边的某个地方存在字符xyz的字符abc(如果不存在,便不能匹配)。 (?=...)被称为肯定顺序环视,因为他需要指定的字符在后面存在才能够完成匹配过程。相反的,(?!...)是否定顺序环视,因为他是在不存在指定字符的条件下的条件下完成匹配。相似的,(?<=...) 和(?<!...) 被称为肯定和否定的逆序环视,因为他们是在当前位置的左边寻找指定的字符存在或者不存在。逆序要比顺序更加局限,因为他不支持*,?和+这样的量词。
相关: 正则表达式由 RegExMatch(), RegExReplace()和SetTitleMatchMode支持。
最后:尽管这个页面介绍了正则表达式中最常用的元字符和一些特性,但是还有比如条件子表达式等相当一部分的其他特性您期望了解的。完整的PCRE手册请访问 www.pcre.org/pcre.txt 。(Hsuda:写到这里,发现AHK里的正则表达式原来用的是PCRE的库,关于PCRE,大家需要了解的是这是个地地道道的传统NFA引擎的正则库,所以,在编写正则表达式的时候是很考验您的优化功力的)
今天要写一个正则表达式,来做前端校验。主要部分是 用来匹配1~4095的数字。
现在就以这个为例,说一下表示范围的正则怎么写。
1、只有1~3位数字,即数字范围:1~999。
分析:第1个数字是1~9,后面的可以出现0~9的数字,最多2位。于是,就有了下面的字符串:
"[1-9]\\d{0,2}+"
2、4位数的,要小于等于4095,即数字范围:1000~4095。
分析:第1位,可以是1~4;第2位,依赖第1位,当第1位是4的时候,第2位只能是0;同理,第3位依赖第2位;第4位依赖第3位。所以,就有了以下代码:
"[1-4]\\d(?<!4[1-9])\\d\\d(?<!409[6-9])"
这里用的是非捕获(?<!X) X,通过零宽度的负 lookbehind 来实现的。
完整代码如下:
- package com.lippeng.helloworld;
- import java.io.UnsupportedEncodingException;
- public class HelloWorld {
- public static void main(String[] args) throws UnsupportedEncodingException {
- // 1~4095
- String regex = "[1-9]\\d{0,2}+|[1-4]\\d(?<!4[1-9])\\d\\d(?<!409[6-9])";
- String[] strArray = { "4094", "4095", "4096", "5000", "4000", "900", "10", "9", "0", "1", "-1", "a", "@" };
- for (String str : strArray) {
- System.out.println(str + " " + str.matches(regex));
- }
- }
- }
测试结果:
- 4094 true
- 4095 true
- 4096 false
- 5000 false
- 4000 true
- 900 true
- 10 true
- 9 true
- 0 false
- 1 true
- -1 false
- a false
- @ false