正则表达式教程里最好的就是Java的这篇。转载给大家。用于UE时,只需要注意Java的转义字符是\,而UE的转义字符是^。大部分情况下做一下置换,表达式就可以通用!UE正则表达式需要首先理解Java中正则的基础概念,至于字符方面,本位后半部分为UE内容。
正则表达式善于处理文本,对匹配、搜索和替换等操作都有意想不到的作用。正因如此,正则表达式现在是作为程序员七种基本技能之一*,因此学习和使用它在工作中都能达到很高的效率。
正则表达式应用于程序设计语言中,首次是出现在 Perl 语言,这也让 Perl 奠定了正则表达式旗手的地位。现在,它已经深入到了所有的程序设计语言中,在程序设计语言中,正则表达式可以说是标准配置了。
Java 中从 JDK 1.4 开始增加了对正则表达式的支持,至此正则表达式成为了 Java 中的基本类库,使用时不需要再导入第三方的类库了。Java 正则表达式的语法来源于象征着正则表达式标准的 Perl 语言,但也不是完全相同的,具体的可以参看 Pattern 类的 API 文档说明。
0.1 什么是正则表达式?
正则表达式(regular expressions)是一种描述字符串集的方法,它是以字符串集中各字符串的共有特征为依据的。正则表达式可以用于搜索、编辑或者是操作文本和数据。它超出了 Java 程序设计语言的标准语法,因此有必要去学习特定的语法来构建正则表达式。正则表达式的变化是复杂的,一旦你理解了它们是如何被构造的话,你就能解析或者构建任意的正则表达式了。
本教程讲授 java.util.regex API 所支持的正则表达式语法,以及介绍几个可运行的例子来说明不同的对象间是如何交互的。在正则表达式的世界中,有不同风格的选择,比如:grep[2]、Perl、Tcl、Python、PHP 和 awk。java.util.regex API 中的正则表达式语法与 Perl 中的最为相似。
0.2 java.util.regex 包是如何描述正则表达式的?
java.util.regex 包主要由三个类所组成:Pattern、Matcher 和 PatternSyntaxException。
- Pattern 对象表示一个已编译的正则表达式。Pattern 类没有提供公共的构造方法。要构建一个模式,首先必须调用公共的静态 compile 方法,它将返回一个 Pattern 对象。这个方法接受正则表达式作为第一个参数。本教程的开始部分将教你必需的语法。
- Matcher 是一个靠着输入的字符串来解析这个模式和完成匹配操作的对象。与 Pattern 相似,Matcher 也没有定义公共的构造方法,需要通过调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
- PatternSyntaxException 对象是一个未检查异常,指示了正则表达式中的一个语法错误。
本教程的最后几节课程会详细地说明各个类。首当其冲的问题是:必须理解正则表达式是如何被构建的,因此下一节引入了一个简单的测试用具,重复地用于探究它们的语法。
2 字符串
在大多数的情况下,API所支持模式匹配的基本形式是匹配字符串,如果正则表达式是foo
,输入的字符串也是 foo,这个匹配将会是成功的,因为这两个字符串是相同的。试着用测试用具来测试一下:
Enter your regex: foo
Enter input string to search: foo
I found the text "foo" starting at index 0 and ending at index 3.
结果确实是成功的。注意当输入的字符串是 3 个字符长度的时候,开始的索引是 0,结束的索引是 3。这个是约定俗成的,范围包括开始的索引,不包括结束的索引,如下图所示:
图 1 字符串“foo”的单元格编号和索引值[4]
字符串中的每一个字符位于其自身的单元格(cell)中,在每个单元格之间有索引指示位。字符串“foo”始于索引 0 处,止于索引 3 处,即使是这些字符它们自己仅占据了 0、1 和 2 号单元格。
就子序列匹配而言,你会注意到一些重叠,下一次匹配开始索引与前一次匹配的结束索引是相同的:
Enter your regex: foo
Enter input string to search: foofoofoo
I found the text "foo" starting at index 0 and ending at index 3.
I found the text "foo" starting at index 3 and ending at index 6.
I found the text "foo" starting at index 6 and ending at index 9.
2.1 元字符
API 也支持许多可以影响模式匹配的特殊字符。把正则表达式改为cat.
并输入字符串“cats”,输出如下所示:
Enter your regex: cat.
Enter input string to search: cats
I found the text "cats" starting at index 0 and ending at index 4.
虽然在输入的字符串中没有点(.),但这个匹配仍然是成功的。这是由于点(.
)是一个元字符(metacharacters)(被这个匹配翻译成了具有特殊意义的字符了)。这个例子为什么能匹配成功的原因在于,元字符.
指的是“任意字符”。
API 所支持的元字符有:(
[
{
\
^
-
$
|
}
]
)
?
*
+
.
注意:在学习过更多的如何构建正则表达式后,你会碰到这些情况:上面的这些特殊字符不应该被处理为元字符。然而也能够使用这个清单来检查一个特殊的字符是否会被认为是元字符。例如,字符 !、@ 和 # 决不会有特殊的意义。
有两种方法可以强制将元字符处理成为普通字符:
1. 在元字符前加上反斜线(\
);
2. 把它放在\Q
(引用开始)和\E
(引用结束)之间[5]。在使用这种技术时,\Q
和\E
能被放于表达式中的任何位置(假设先出现\Q
[6])
3 字符类
如果你曾看过 Pattern 类的说明,会看到一些构建正则表达式的概述。在这一节中你会发现下面的一些表达式:
[abc] | a, b 或 c(简单类) |
[^abc] | 除 a, b 或 c 之外的任意字符(取反) |
[a-zA-Z] | a 到 z,或 A 到 Z,包括(范围) |
[a-d[m-p]] | a 到 d,或 m 到 p:[a-dm-p] (并集) |
[a-z&&[def]] | d,e 或 f(交集) |
[a-z&&[^bc]] | 除 b 和 c 之外的 a 到 z 字符:[ad-z] (差集) |
[a-z&&[^m-p]] | a 到 z,并且不包括 m 到 p:[a-lq-z] (差集) |
左边列指定正则表达式构造,右边列描述每个构造的匹配的条件。
注意:“字符类(character class)”这个词中的“类(class)”指的并不是一个 .class 文件。在正则表达式的语义中,字符类是放在方括号里的字符集,指定了一些字符中的一个能被给定的字符串所匹配。
3.1 简单类(Simple Classes)
字符类最基本的格式是把一些字符放在一对方括号内。例如:正则表达式[bcr]at
会匹配“bat”、“cat”或者“rat”,这是由于其定义了一个字符类(接受“b”、“c”或“r”中的一个字符)作为它的首字符。
Enter your regex: [bcr]at
Enter input string to search: bat
I found the text "bat" starting at index 0 and ending at index 3.
Enter your regex: [bcr]at
Enter input string to search: cat
I found the text "cat" starting at index 0 and ending at index 3.
Enter your regex: [bcr]at
Enter input string to search: rat
I found the text "rat" starting at index 0 and ending at index 3.
Enter your regex: [bcr]at
Enter input string to search: hat
No match found.
在上面的例子中,在第一个字符匹配字符类中所定义字符中的一个时,整个匹配就是成功的。
3.1.1 否定
要匹配除那些列表之外所有的字符时,可以在字符类的开始处加上^
元字符,这种就被称为否定(negation)。
Enter your regex: [^bcr]at
Enter input string to search: bat
No match found.
Enter your regex: [^bcr]at
Enter input string to search: cat
No match found.
Enter your regex: [^bcr]at
Enter input string to search: rat
No match found.
Enter your regex: [^bcr]at
Enter input string to search: hat
I found the text "hat" starting at index 0 and ending at index 3.
在输入的字符串中的第一个字符不包含在字符类中所定义字符中的一个时,匹配是成功的。
3.1.2 范围
有时会想要定义一个包含值范围的字符类,诸如,“a 到 h”的字母或者是“1 到 5”的数字。指定一个范围,只要在被匹配的首字符和末字符间插入-
元字符,比如:[1-5]
或者是[a-h]
。也可以在类里每个的边上放置不同的范围来提高匹配的可能性,例如:[a-zA-Z]
将会匹配 a 到 z(小写字母)或者 A 到 Z(大写字母)中的任何一个字符。
下面是一些范围和否定的例子:
Enter your regex: [a-c]
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
Enter your regex: [a-c]
Enter input string to search: b
I found the text "b" starting at index 0 and ending at index 1.
Enter your regex: [a-c]
Enter input string to search: c
I found the text "c" starting at index 0 and ending at index 1.
Enter your regex: [a-c]
Enter input string to search: d
No match found.
Enter your regex: foo[1-5]
Enter input string to search: foo1
I found the text "foo1" starting at index 0 and ending at index 4.
Enter your regex: foo[1-5]
Enter input string to search: foo5
I found the text "foo5" starting at index 0 and ending at index 4.
Enter your regex: foo[1-5]
Enter input string to search: foo6
No match found.
Enter your regex: foo[^1-5]
Enter input string to search: foo1
No match found.
Enter your regex: foo[^1-5]
Enter input string to search: foo6
I found the text "foo6" starting at index 0 and ending at index 4.
3.1.3 并集
可以使用并集(union)来建一个由两个或两个以上字符类所组成的单字符类。构建一个并集,只要在一个字符类的边上嵌套另外一个,比如:[0-4[6-8]]
,这种奇特方式构建的并集字符类,可以匹配 0,1,2,3,4,6,7,8 这几个数字。
Enter your regex: [0-4[6-8]]
Enter input string to search: 0
I found the text "0" starting at index 0 and ending at index 1.
Enter your regex: [0-4[6-8]]
Enter input string to search: 5
No match found.
Enter your regex: [0-4[6-8]]
Enter input string to search: 6
I found the text "6" starting at index 0 and ending at index 1.
Enter your regex: [0-4[6-8]]
Enter input string to search: 8
I found the text "8" starting at index 0 and ending at index 1.
Enter your regex: [0-4[6-8]]
Enter input string to search: 9
No match found.
3.1.4 交集
建一个仅仅匹配自身嵌套类中公共部分字符的字符类时,可以像[0-9&&[345]]
中那样使用&&
。这种方式构建出来的交集(intersection)简单字符类,仅仅以匹配两个字符类中的 3,4,5 共有部分。
Enter your regex: [0-9&&[345]]
Enter input string to search: 3
I found the text "3" starting at index 0 and ending at index 1.
Enter your regex: [0-9&&[345]]
Enter input string to search: 4
I found the text "4" starting at index 0 and ending at index 1.
Enter your regex: [0-9&&[345]]
Enter input string to search: 5
I found the text "5" starting at index 0 and ending at index 1.
Enter your regex: [0-9&&[345]]
Enter input string to search: 2
No match found.
Enter your regex: [0-9&&[345]]
Enter input string to search: 6
No match found.
下面演示两个范围交集的例子:
Enter your regex: [2-8&&[4-6]]
Enter input string to search: 3
No match found.
Enter your regex: [2-8&&[4-6]]
Enter input string to search: 4
I found the text "4" starting at index 0 and ending at index 1.
Enter your regex: [2-8&&[4-6]]
Enter input string to search: 5
I found the text "5" starting at index 0 and ending at index 1.
Enter your regex: [2-8&&[4-6]]
Enter input string to search: 6
I found the text "6" starting at index 0 and ending at index 1.
Enter your regex: [2-8&&[4-6]]
Enter input string to search: 7
No match found.
3.1.5 差集
最后,可以使用差集(subtraction)来否定一个或多个嵌套的字符类,比如:[0-9&&[^345]]
,这个是构建一个匹配除 3,4,5 之外所有 0 到 9 间数字的简单字符类。
Enter your regex: [0-9&&[^345]]
Enter input string to search: 2
I found the text "2" starting at index 0 and ending at index 1.
Enter your regex: [0-9&&[^345]]
Enter input string to search: 3
No match found.
Enter your regex: [0-9&&[^345]]
Enter input string to search: 4
No match found.
Enter your regex: [0-9&&[^345]]
Enter input string to search: 5
No match found.
Enter your regex: [0-9&&[^345]]
Enter input string to search: 6
I found the text "6" starting at index 0 and ending at index 1.
Enter your regex: [0-9&&[^345]]
Enter input string to search: 9
I found the text "9" starting at index 0 and ending at index 1.
到此为止,已经涵盖了如何建立字符类的部分。在继续下一节之前,可以试着回想一下那张字符类表。
4 预定义字符类
Pattern 的 API 包有许多有用的预定义字符类(predefined character classes),提供了常用正则表达式的简写形式。
. | 任何字符(匹配或者不匹配行结束符) |
\d | 数字字符:[0-9] |
\D | 非数字字符:[^0-9] |
\s | 空白字符:[\t\n\x0B\f\r] |
\S | 非空白字符:[^\s] |
\w | 单词字符:[a-zA-Z_0-9] |
\W | 非单词字符:[^\w] |
上表中,左列是构造右列字符类的简写形式。例如:\d
指的是数字范围(0~9),\w
指的是单词字符(任何大小写字母、下划线或者是数字)。无论何时都有可能使用预定义字符类,它可以使代码更易阅读,更易从难看的字符类中排除错误。
以反斜线(\
)开始的构造称为转义构造(escaped constructs)。回顾一下在 字符串 一节中的转义构造,在那里我们提及了使用反斜线,以及用于引用的\Q
和\E
。在字符串中使用转义构造,必须在一个反斜线前再增加一个反斜用于字符串的编译,例如:
private final String REGEX = "\\d"; // 单个数字
这个例子中\d
是正则表达式,另外的那个反斜线是用于代码编译所必需的。但是测试用具读取的表达式,是直接从控制台中输入的,因此不需要那个多出来的反斜线。
下面的例子说明了预字义字符类的用法:
Enter your regex: .
Enter input string to search: @
I found the text "@" starting at index 0 and ending at index 1.
Enter your regex: .
Enter input string to search: 1
I found the text "1" starting at index 0 and ending at index 1.
Enter your regex: .
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
Enter your regex: \d
Enter input string to search: 1
I found the text "1" starting at index 0 and ending at index 1.
Enter your regex: \d
Enter input string to search: a
No match found.
Enter your regex: \D
Enter input string to search: 1
No match found.
Enter your regex: \D
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
Enter your regex: \s
Enter input string to search:
I found the text " " starting at index 0 and ending at index 1.
Enter your regex: \s
Enter input string to search: a
No match found.
Enter your regex: \S
Enter input string to search:
No match found.
Enter your regex: \S
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
Enter your regex: \w
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
Enter your regex: \w
Enter input string to search: !
No match found.
Enter your regex: \W
Enter input string to search: a
No match found.
Enter your regex: \W
Enter input string to search: !
I found the text "!" starting at index 0 and ending at index 1.
在开始的三个例子中,正则表达式是简单的,.
(“点”元字符)表示“任意字符”,因此,在所有的三个例子(随意地选取了“@”字符,数字和字母)中都是匹配成功的。在接下来的例子中,都使用了预定义字符类表格中的单个正则表达式构造。你应该可以根据这张表指出前面每个匹配的逻辑:
\d
匹配数字字符
\s
匹配空白字符
\w
匹配单词字符
也可以使用意思正好相反的大写字母:
\D
匹配非数字字符
\S
匹配非空白字符
\W
匹配非单词字符
5 量词
这一节我们来看一下贪婪(greedy)、勉强(reluctant)和侵占(possessive)量词,来匹配指定表达式X
的次数。
量词(quantifiers)允许指定匹配出现的次数,方便起见,当前 Pattern API 规范下,描述了贪婪、勉强和侵占三种量词。首先粗略地看一下,量词X?
、X??
和X?+
都允许匹配 X 零次或一次,精确地做同样的事情,但它们之间有着细微的不同之处,在这节结束前会进行说明。
量 词 种 类 | 意 义 | ||
贪婪 | 勉强 | 侵占 | |
X? | X?? | X?+ | 匹配 X 零次或一次 |
X* | X*? | X*+ | 匹配 X 零次或多次 |
X+ | X+? | X++ | 匹配 X 一次或多次 |
X{n} | X{n}? | X{n}+ | 匹配 X n 次 |
X{n,} | X{n,}? | X{n,}+ | 匹配 X 至少 n 次 |
X{n,m} | X{n,m}? | X{n,m}+ | 匹配 X 至少 n 次,但不多于 m 次 |
那我们现在就从贪婪量词开始,构建三个不同的正则表达式:字母a
后面跟着?
、*
和+
。接下来看一下,用这些表达式来测试输入的字符串是空字符串时会发生些什么:
Enter your regex: a?
Enter input string to search:
I found the text "" starting at index 0 and ending at index 0.
Enter your regex: a*
Enter input string to search:
I found the text "" starting at index 0 and ending at index 0.
Enter your regex: a+
Enter input string to search:
No match found.
5.1 零长度匹配
在上面的例子中,开始的两个匹配是成功的,这是因为表达式a?
和a*
都允许字符出现零次。就目前而言,这个例子不像其他的,也许你注意到了开始和结束的索引都是 0。输入的空字符串没有长度,因此该测试简单地在索引 0 上匹配什么都没有,诸如此类的匹配称之为零长度匹配(zero-length matches)。零长度匹配会出现在以下几种情况:输入空的字符串、在输入字符串的开始处、在输入字符串最后字符的后面,或者是输入字符串中任意两个字符之间。由于它们开始和结束的位置有着相同的索引,因此零长度匹配是容易被发现的。
我们来看一下关于零长度匹配更多的例子。把输入的字符串改为单个字符“a”,你会注意到一些有意思的事情:
Enter your regex: a?
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.
Enter your regex: a*
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.
Enter your regex: a+
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
所有的三个量词都是用来寻找字母“a”的,但是前面两个在索引 1 处找到了零长度匹配,也就是说,在输入字符串最后一个字符的后面。回想一下,匹配把字符“a”看作是位于索引 0 和索引 1 之间的单元格中,并且测试用具一直循环下去直到不再有匹配为止。依赖于所使用的量词不同,最后字符后面的索引“什么也没有”的存在可以或者不可以触发一个匹配。
现在把输入的字符串改为一行 5 个“a”时,会得到下面的结果:
Enter your regex: a?
Enter input string to search: aaaaa
I found the text "a" starting at index 0 and ending at index 1.
I found the text "a" starting at index 1 and ending at index 2.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "a" starting at index 3 and ending at index 4.
I found the text "a" starting at index 4 and ending at index 5.
I found the text "" starting at index 5 and ending at index 5.
Enter your regex: a*
Enter input string to search: aaaaa
I found the text "aaaaa" starting at index 0 and ending at index 5.
I found the text "" starting at index 5 and ending at index 5.
Enter your regex: a+
Enter input string to search: aaaaa
I found the text "aaaaa" starting at index 0 and ending at index 5.
在“a”出现零次或一次时,表达式a?
寻找到所匹配的每一个字符。表达式a*
找到了两个单独的匹配:第一次匹配到所有的字母“a”,然后是匹配到最后一个字符后面的索引 5。最后,a+
匹配了所有出现的字母“a”,忽略了在最后索引处“什么都没有”的存在。
在这里,你也许会感到疑惑,开始的两个量词在遇到除了“a”的字母时会有什么结果。例如,在“ababaaaab”中遇到了字母“b”会发生什么呢?
下面我们来看一下:
Enter your regex: a?
Enter input string to search: ababaaaab
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "" starting at index 3 and ending at index 3.
I found the text "a" starting at index 4 and ending at index 5.
I found the text "a" starting at index 5 and ending at index 6.
I found the text "a" starting at index 6 and ending at index 7.
I found the text "a" starting at index 7 and ending at index 8.
I found the text "" starting at index 8 and ending at index 8.
I found the text "" starting at index 9 and ending at index 9.
Enter your regex: a*
Enter input string to search: ababaaaab
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "" starting at index 3 and ending at index 3.
I found the text "aaaa" starting at index 4 and ending at index 8.
I found the text "" starting at index 8 and ending at index 8.
I found the text "" starting at index 9 and ending at index 9.
Enter your regex: a+
Enter input string to search: ababaaaab
I found the text "a" starting at index 0 and ending at index 1.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "aaaa" starting at index 4 and ending at index 8.
即使字母“b”在单元格 1、3、8 中出现,但在这些位置上的输出报告了零长度匹配。正则表达式a?
不是特意地去寻找字母“b”,它仅仅是去找字母“a”存在或者其中缺少的。如果量词允许匹配“a”零次,任何输入的字符不是“a”时将会作为零长度匹配。在前面的例子中,根据讨论的规则保证了 a 被匹配。
对于要精确地匹配一个模式 n 次时,可以简单地在一对花括号内指定一个数值:
Enter your regex: a{3}
Enter input string to search: aa
No match found.
Enter your regex: a{3}
Enter input string to search: aaa
I found the text "aaa" starting at index 0 and ending at index 3.
Enter your regex: a{3}
Enter input string to search: aaaa
I found the text "aaa" starting at index 0 and ending at index 3.
这里,正则表确定式a{3}
在一行中寻找连续出现三次的字母“a”。第一次测试失败的原由在于,输入的字符串没有足够的 a 用来匹配;第二次测试输出的字符串正好包括了三个“a”,触发了一次匹配;第三次测试也触发了一次匹配,这是由于在输出的字符串的开始部分正好有三个“a”。接下来的事情与第一次的匹配是不相关的,如果这个模式将在这一点后继续出现,那它将会触发接下来的匹配:
Enter your regex: a{3}
Enter input string to search: aaaaaaaaa
I found the text "aaa" starting at index 0 and ending at index 3.
I found the text "aaa" starting at index 3 and ending at index 6.
I found the text "aaa" starting at index 6 and ending at index 9.
对于需要一个模式出现至少 n 次时,可以在这个数字后面加上一个逗号(,
):
Enter your regex: a{3,}
Enter input string to search: aaaaaaaaa
I found the text "aaaaaaaaa" starting at index 0 and ending at index 9.
输入一样的字符串,这次测试仅仅找到了一个匹配,这是由于一个中有九个“a”满足了“至少”三个“a”的要求。
最后,对于指定出现次数的上限,可以在花括号添加第二个数字。
Enter your regex: a{3,6} // 寻找一行中至少连续出现 3 个(但不多于 6 个)“a”
Enter input string to search: aaaaaaaaa
I found the text "aaaaaa" starting at index 0 and ending at index 6.
I found the text "aaa" starting at index 6 and ending at index 9.
这里,第一次匹配在 6 个字符的上限时被迫终止了。第二个匹配包含了剩余的三个 a(这是匹配所允许最小的字符个数)。如果输入的字符串再少掉一个字母,这时将不会有第二个匹配,之后仅剩余两个 a。
6 捕获组
在上一节中,学习了每次如何把量词放在一个字符、字符类或者捕获组中。到目前为止,还没有详细地讨论过捕获组的概念。
捕获组(capturing group)是将多个字符作为单独的单元来对待的一种方式。构建它们可以通过把字符放在一对圆括号中而成为一组。例如,正则表达式(dog)
建了单个的组,包括字符“d”“o”和“g”。匹配捕获组输入的字符串部分将会存放于内存中,稍后通过反向引用再次调用。(在 6.2 节 中将会讨论反向引用)
6.1 编号方式返回目录
在 Pattern 的 API 描述中,捕获组通过从左至右计算开始的圆括号进行编号。例如,在表达式((A)(B(C)))
中,有下面的四组:
1. ((A)(B(C)))
2. (A)
3. (B(C))
4. (C)
要找出当前的表达式中有多少组,通过调用 Matcher 对象的 groupCount 方法。groupCount 方法返回 int 类型值,表示当前 Matcher 模式中捕获组的数量。例如,groupCount 返回 4 时,表示模式中包含有 4 个捕获组。
有一个特别的组——组 0,它表示整个表达式。这个组不包括在 groupCount 的报告范围内。以(?
开始的组是纯粹的非捕获组(non-capturing group),它不捕获文本,也不作为组总数而计数。(可以看 8 Pattern 类的方法 一节中非捕获组的例子。)
Matcher 中的一些方法,可以指定 int 类型的特定组号作为参数,因此理解组是如何编号的是尤为重要的。
public int start(int group):返回之前的匹配操作期间,给定组所捕获的子序列的初始索引。
public int end(int group):返回之前的匹配操作期间,给定组所捕获子序列的最后字符索引加 1。
public String group (int group):返回之前的匹配操作期间,通过给定组而捕获的输入子序列。
6.2 反向引用
匹配输入字符串的捕获组部分会存放在内存中,通过反向引用(backreferences)稍后再调用。在正则表达式中,反向引用使用反斜线(\
)后跟一个表示需要再调用组号的数字来表示。例如,表达式(\d\d)
定义了匹配一行中的两个数字的捕获组,通过反向引用\1
,表达式稍候会被再次调用。
匹配两个数字,且后面跟着两个完全相同的数字时,就可以使用(\d\d)\1
作为正则表达式:
Enter your regex: (\d\d)\1
Enter input string to search: 1212
I found the text "1212" starting at index 0 and ending at index 4.
如果更改最后的两个数字,这时匹配就会失败:
Enter your regex: (\d\d)\1
Enter input string to search: 1234
No match found.
对于嵌套的捕获组而言,反向引用采用完全相同的方式进行工作,即指定一个反斜线加上需要被再次调用的组号。
7 边界匹配器
就目前而言,我们的兴趣在于指定输入字符串中某些位置是否有匹配,还没有考虑到字符串的匹配产生在什么地方。
通过指定一些边界匹配器(boundary matchers)的信息,可以使模式匹配更为精确。比如说你对某个特定的单词感兴趣,并且它只出现在行首或者是行尾时。又或者你想知道匹配发生在单词边界(word boundary),或者是上一个匹配的尾部。
下表中列出了所有的边界匹配器及其说明。
^ | 行首 |
$ | 行尾 |
\b | 单词边界 |
\B | 非单词边界 |
\A | 输入的开头 |
\G | 上一个匹配的结尾 |
\Z | 输入的结尾,仅用于最后的结束符(如果有的话) |
\z | 输入的结尾 |
接下来的例子中,说明了^
和$
边界匹配器的用法。注意上表中,^
匹配行首,$
匹配行尾。
Enter your regex: ^dog$
Enter input string to search: dog
I found the text "dog" starting at index 0 and ending at index 3.
Enter your regex: ^dog$
Enter input string to search: dog
No match found.
Enter your regex: \s*dog$
Enter input string to search: dog
I found the text " dog" starting at index 0 and ending at index 15.
Enter your regex: ^dog\w*
Enter input string to search: dogblahblah
I found the text "dogblahblah" starting at index 0 and ending at index 11.
第一个例子的匹配是成功的,这是因为模式占据了整个输入的字符串。第二个例子失败了,是由于输入的字符串在开始部分包含了额外的空格。第三个例子指定的表达式是不限的空格,后跟着在行尾的 dog。第四个例子,需要 dog 放在行首,后面跟的是不限数量的单词字符。
对于检查一个单词开始和结束的边界模式(用于长字符串里子字符串),这时可以在两边使用\b
,例如\bdog\b
。
Enter your regex: \bdog\b
Enter input string to search: The dog plays in the yard.
I found the text "dog" starting at index 4 and ending at index 7.
Enter your regex: \bdog\b
Enter input string to search: The doggie plays in the yard.
No match found.
比较重要的,常用的部分就是以上内容。虽然是Java的教程,但是正则表达式的思想是一致的。如果需要完整内容(贪婪啊、侵占啊等),请从这里下载Java正则表达式教程。希望对勤奋的你有所帮助!本文主要摘取自Java正则表达式教程,感谢作者的奉献。谢谢!
======================================华丽的分界线=============================================
Java的正则表达式教程说明了正则的原理,接下来我们看一下UE的正则表达式在使用时,需要注意什么:
用UltraEdit允许正则表达式在许多搜索和替换功能搜索菜单下。
正则表达式允许更复杂的搜索和替换将要执行的功能在一个单一的操作。
有传统的语法的两种可能的设置,可以使用。第一见下表示出了在较早版本的UltraEdit的使用的原始的UltraEdit语法。 第二表给出了可选的“UNIX”样式的正则表达式。这可以从被启用配置部分。
正则表达式(UltraEdit的语法):
符号 | 功能 |
% | 匹配行的开始 - 显示搜索字符串必须在开始 行的,但不包括所得到的字符串中的任何行终止字符 选中。 |
$ | 匹配一行的末尾 - 显示搜索字符串必须在一行的末尾 但不包括选定得到的字符串中的任何行终止字符。 |
? | 匹配除换行符任何单个字符。 |
* | 匹配任何数量的换行符以外的任何字符的出现。 |
+ | 匹配一个或多个前述单个字符/字符集。 最后一个 字符的发生,必须找到。 |
++ | 匹配前面的一个字符/字符集零次或多次。 才不是 匹配重复的换行符。 |
^b | 匹配一个分页符。 |
^p | 匹配一个换行符(CR/ LF)(段)(DOS文件) |
^r | 匹配一个换行符(仅CR)(段落)(MAC文件) |
^n | 匹配一个换行符(仅LF)(段)(UNIX文件) |
^t | 匹配一个制表符 |
[xyz] | 一个字符集。匹配括号中的任何字符。 |
[~xyz] | 负字符集。匹配之间的不包括括号内的任何字符 换行符。 |
^{A^}^{B^} | 匹配表达式A或B |
^ | 覆盖下面的正则表达式字符 |
^(...^) | 支架或标签在替换命令中使用的表达式。正则表达式 可能有多达9标记表达,根据其在常规顺序编号 表达。
相应的替换表达式是^ x的,在1-9范围内的X.例如: 如果 ^(h*o^) ^(f*s^) 火柴 "hello folks", ^2 ^1 将其替换 "folks hello". |
注 - ^指的是字符“^”不是控制键+值。
例子:
m?n 火柴 "man", "men", "min" 但不是 "moon".
t*t 火柴 "test", "tonight" 和 "tea time" (the "tea t" portion) 但不是 "tea
time"之间(换行符 "tea "和 "time")。
Te+st 火柴 "test", "teest", "teeeest" etc. 但不匹配 "tst".
[aeiou] 每一个小写元音匹配
[,.?] 匹配一个字面",", "." or "?".
[0-9a-z] 任何数字或小写字母相匹配
[~0-9] 任何字符匹配除了数字(〜表示不是以下)
你可以搜索的表达式A或B,如下所示:
"^{John^}^{Tom^}"
这将搜索John或汤姆的发生。应该有之间没有任何东西
两个表达式。
您可以结合A或B和C或D在相同的搜索如下:
"^{John^}^{Tom^} ^{Smith^}^{Jones^}"
这将搜索John或汤姆随后史密斯和琼斯。
下表所示为“UNIX”样式的正则表达式的语法。
正则表达式(Unix的语法):
符号 | 功能 |
\ | 指示下一个字符有特殊的意义。在它自己的“N”相匹配的 字符“n”。 “\n”匹配一个换行符或换行符。请参见下面的例子 (\ D,\ F,\ n等)。 |
^ | 相配/锚定行的开始。 |
$ | 相配/锚定行的结尾。 |
* | 匹配前面的一个字符/字符集零次或多次。 |
+ | 相配前述单个字符/字符集的一个或更多次。 至少 前面的字符出现一次或前面的字符的人物之一 集必须被发现。 |
. | 匹配除换行符任何单个字符。不匹配重复换行。 |
(expression) | 支架或标签在替换命令中使用的表达式。正则表达式 可能有多达9标记表达,根据其在常规顺序编号 表达。
相应的替换表达式是\ x,对于x的范围是1-9。例如: 如果 (h.*o) (f.*s) 火柴 "hello folks", \2 \1 将其替换 "folks hello"。 |
[xyz] | 一个字符集。匹配括号中的任何字符。 |
[^xyz] | 负字符集。匹配之间的不包括括号内的任何字符换行符。 |
\d | 匹配一个数字字符。等价于[0-9]。 |
\D | 匹配一个非数字字符。等价于[^0-9]。 |
\f | 匹配一个换页符。 |
\n | 匹配一个换行符。 |
\r | 匹配一个回车符。 |
\s | 匹配包括空格,制表符,换页等,但不换行的空白。 |
\S | 匹配任何非空白字符,但不换行。 |
\t | 匹配一个制表符。 |
\v | 匹配一个垂直制表符。 |
\w | 匹配任何字母数字字符,包括下划线。 |
\W | 匹配除字母数字字符的任意字符和下划线。 |
\p | 匹配CR / LF(等同于\ r \ n)的匹配DOS行终止。 |
注 - ^指的是字符“^”不是控制键+值。
例子:
m.n 火柴"man", "men", "min" 但不是 "moon".
Te+st 火柴"test", "teest", "teeeest" etc. 但不是"tst".
Te*st 火柴"test", "teest", "teeeest" etc. 和"tst".
[aeiou] 每一个小写元音匹配
[,.?] 匹配一个字面上的“,”,“。” 要么 ”?”。
[0-9a-z] 任何数字或小写字母相匹配
[^0-9] 任何字符匹配除了数字(^表示不以下)
你可以搜索的表达式A或B,如下所示:
"(John|Tom)"
这将搜索John或汤姆的发生。应该有之间没有任何东西两个表达式。
您可以结合A或B和C或D在相同的搜索如下:
"(John|Tom) (Smith|Jones)"
这将搜索John或汤姆随后史密斯和琼斯。
如果没有选择正则表达式(即没有正则表达式的使用有效)为查找/替换以下特殊字符也都在寻找有效的,
替换字段:
符号 | 功能 |
^^ | 匹配一个“^”字符 |
^s | 取代有活动文件窗口的选择(高亮显示的)文本。 |
^c | 被取代为剪贴板中的内容。 |
^b | 匹配一个分页符 |
^p | 匹配一个换行符(CR/ LF)(段)(DOS文件) |
^r | 匹配一个换行符(仅CR)(段落)(MAC文件) |
^n | 匹配一个换行符(仅LF)(段)(UNIX文件) |
^t | 匹配一个制表符 |
注 - ^指的是字符“^”不是控制键+值。
有关Perl兼容的正则表达式的信息,用UltraEdit/ UEStudio的现在支持使用Perl风格的正则表达式 Boost C ++库。Perl的正则表达式语法的基础上,通过编程语言使用Perl的。如下文所示:
Perl的正则表达式语法
在Perl的正则表达式,所有的字符匹配自身除以下特殊字符:
.[{()\*+?|^$}]
通配符
单个字符“。”外使用的字符集将匹配任何单字符。
锚
A'^'字符应匹配行的开始。
A“$”字符应匹配行的末尾。
标记子表达式
一节开始(和结束)作为一个标记子表达式。不管匹配子表达在单独的字段由匹配算法拆出。标记
子表达式也可以重复进行,或由一个向后引用提及。
轮流
该|运营商将匹配它的参数,因此,例如:ABC| DEF将匹配无论“ABC”或“DEF”。
圆括号可以用于组交替,例如:AB(D| EF)将匹配的“ABD”或“ABEF”。
空替代品是不允许(这些几乎都是错误的),但如果你真要一个空的其他用途(:)作为一个占位符,例如?
"|abc" 是不是有效的表达式,但
"(?:)|abc" 是,等效,也表达:
"(?:abc)??" 具有完全相同的效果。
字符集
字符集是用括号表达开始[和结尾],它定义一组字符,并且匹配任何单个字符是集合的成员。
方括号表达式可能包含以下的任意组合:
单个字符
例如[ABC],将匹配任何字符'A','B'或'C'的。
字符范围
例如[A-C]会匹配范围'a'到'C'任何单个字符。 默认,对于POSIX Perl的正则表达式,字符x是范围Ÿ到z范围内,如果它核对该范围内;这导致特定于语言环境的行为。
否定
如果托架表达了^字符开头,那么它补匹配它包含的字符,例如[^ A-C]的匹配,是不是任何字符在范围A-C。
字符类
该形式的表达式[:名称:[]]匹配命名字符类“名”,为例 [[:lower:]] 任何小写字符匹配。下面的字符类名总是支持的:
名称 | POSIX标准 | 描述 |
alnum | 是 | 任何字母数字字符。 |
alpha | 是 | 任何字母字符。 |
blank | 是 | 任何空白字符不是一个行分隔符。 |
cntrl | 是 | 任何控制字符。 |
d | 没有 | 任何十进制数字 |
digit | 是 | 任何十进制数字。 |
graph | 是 | 任何图形字符。 |
l | 没有 | 任何小写字符。 |
lower | 是 | 任何小写字符。 |
| 是 | 任何可打印的字符。 |
punct | 是 | 任何标点字符。 |
s | 没有 | 任何空白字符。 |
space | 是 | 任何空白字符。 |
unicode | 没有 | 任何扩展字符的代码点是高于价值255。 |
u | 没有 | 任何大写字母。 |
upper | 是 | 任何大写字母。 |
w | 没有 | 任何单词字符(字母数字字符加下划线)。 |
word | 没有 | 任何单词字符(字母数字字符加下划线)。 |
xdigit | 是 | 任何十六进制数字字符。 |
逃逸
转义前缀的任何特殊字符应匹配本身。下面逃生序列也被支持:
逃逸匹配特定的字符
下面的转义序列是单个字符所有同义词:
逃逸 | 字符 |
\a | '\a' |
\e | 0x1B |
\f | \f |
\n | \n |
\r | \r |
\t | \t |
\v | \v |
\b | \b (但只能在字符类声明)。 |
\cX | 一个ASCII转义序列 - 其代码点的字符是X%32 |
\xdd | 十六进制转义序列 - 单个字符的代码点是一致 0xdd。 |
\x{dddd} | 十六进制转义序列 - 单个字符的代码点是一致 0xdddd。 |
\0ddd | 八进制转义序列 - 匹配单个字符的代码点是0ddd。 |
\N{name} | 匹配有符号名名单个字符。例如\ N {}换行符 单个字符\ n匹配。 |
“单字符”字符类
任何逃脱字符x,如果x是一个字符类的名称应匹配任何字符作为该类别的成员,并且任何转义字符x,如果x是的名称
一个字符类,应在该类不匹配任何字符。以下是默认支持:
转义序列 | 相当于 |
\d | [[:digit:]] |
\l | [[:lower:]] |
\s | [[:space:]] |
\u | [[:upper:]] |
\w | [[:word:]] |
\D | [^[:digit:]] |
\L | [^[:lower:]] |
\S | [^[:space:]] |
\U | [^[:upper:]] |
\W | [^[:word:]] |
字边界
下面的转义序列匹配单词的边界:
\< | 匹配一个单词的开始。 |
\> | 匹配的字的末尾。 |
\b | 匹配一个单词边界(单词的开始或结束)。 |
\B | 仅匹配时,不是在一个字边界。 |
欲了解更多信息/选项请参阅 Boost库Perl的正则表达式的语法页面。