JAVA正则表达式 教程

  • Post author:
  • Post category:java


第一篇:什么是正则表达式?

在学习JAVA的正则表达式之前,先介绍一下什么是正则表达式:

1、正则表达式是一种强大而灵活的文本处理工具;

2、在技术上,正则表达式实现了对字符串的操作,在先前,这些任务一般都指派给了JAVA中的String、StringBuffer和StringTOkenizer这些类;

3、正则表达式一般和I/O联合使用;

4、正则表达式可以让我们以编程方式指定那些可以再输入字符串中发现的复杂的文本模式,一旦我们发现了这些模式,那么就可以按照任何我们所希望的方式进行处理了;

5、正则表达式提供了一种紧凑的、动态的语言,能够以一种完全通用的方式来解决各种字符串处理(例如:匹配、选择、编辑及验证)问题;

第二篇:如何创建正则表达式?

好了,看到这里我想大家对正则表达式应该已经有了一定的了解了吧,下面我来介绍一下如何创建正则表达式:

要 学习正则表达式就必须了解正则表达式的构造集,只有了解了构造集,掌握了模式匹配的原则和方法,你才能写出适合你需要的正则表达式,打个比方,要构造一个 房屋模型,就要使用这一个个的积木,让他们以适当的方式进行拼合,构造集中的匹配符号就好像是搭建房屋模型的一个个小积木,用于创建正则表达式的完全构造 列表可以在javadocs的Pattern类中找到,为了方便查询,我在这里也把这些构造集列了出来,以供参考(注:摘自JDK 5.0 Documentation)

————————————————————————————————————————————————

资料参考:正则表达式的构造摘要

1)字符

x 字符 x

// 反斜线字符

/0n 带有八进制值 0 的字符 n (0 <= n <= 7)

/0nn 带有八进制值 0 的字符 nn (0 <= n <= 7)

/0mnn 带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7)

/xhh 带有十六进制值 0x 的字符 hh

/uhhhh 带有十六进制值 0x 的字符 hhhh

/t 制表符 (‘/u0009’)

/n 新行(换行)符 (‘/u000A’)

/r 回车符 (‘/u000D’)

/f 换页符 (‘/u000C’)

/a 报警 (bell) 符 (‘/u0007’)

/e 转义符 (‘/u001B’)

/cx 对应于 x 的控制符

2)字符类

[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]] a 到 z,除了 b 和 c:[ad-z](减去)

[a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去)

3)预定义字符类

. 任何字符(与行结束符可能匹配也可能不匹配)

/d 数字:[0-9]

/D 非数字: [^0-9]

/s 空白字符:[ /t/n/x0B/f/r]

/S 非空白字符:[^/s]

/w 单词字符:[a-zA-Z_0-9]

/W 非单词字符:[^/w]

4)POSIX 字符类(仅 US-ASCII)

/p{Lower} 小写字母字符:[a-z]

/p{Upper} 大写字母字符:[A-Z]

/p{ASCII} 所有 ASCII:[/x00-/x7F]

/p{Alpha} 字母字符:[/p{Lower}/p{Upper}]

/p{Digit} 十进制数字:[0-9]

/p{Alnum} 字母数字字符:[/p{Alpha}/p{Digit}]

/p{Punct} 标点符号:!”#$%&'()*+,-./:;<=>?@[/]^_`{|}~

/p{Graph} 可见字符:[/p{Alnum}/p{Punct}]

/p{Print} 可打印字符:[/p{Graph}/x20]

/p{Blank} 空格或制表符:[ /t]

/p{Cntrl} 控制字符:[/x00-/x1F/x7F]

/p{XDigit} 十六进制数字:[0-9a-fA-F]

/p{Space} 空白字符:[ /t/n/x0B/f/r]

5)java.lang.Character 类(简单的 java 字符类型)

/p{javaLowerCase} 等效于 java.lang.Character.isLowerCase()

/p{javaUpperCase} 等效于 java.lang.Character.isUpperCase()

/p{javaWhitespace} 等效于 java.lang.Character.isWhitespace()

/p{javaMirrored} 等效于 java.lang.Character.isMirrored()

6)Unicode 块和类别的类

/p{InGreek} Greek 块(简单块)中的字符

/p{Lu} 大写字母(简单类别)

/p{Sc} 货币符号

/P{InGreek} 所有字符,Greek 块中的除外(否定)

[/p{L}&&[^/p{Lu}]]  所有字母,大写字母除外(减去)

7)边界匹配器

^ 行的开头

$ 行的结尾

/b 单词边界

/B 非单词边界

/A 输入的开头

/G 上一个匹配的结尾

/Z 输入的结尾,仅用于最后的结束符(如果有的话)

/z 输入的结尾

8)Greedy 数量词

X? X,一次或一次也没有

X* X,零次或多次

X+ X,一次或多次

X{n} X,恰好 n 次

X{n,} X,至少 n 次

X{n,m} X,至少 n 次,但是不超过 m 次

9)Reluctant 数量词

X?? X,一次或一次也没有

X*? X,零次或多次

X+? X,一次或多次

X{n}? X,恰好 n 次

X{n,}? X,至少 n 次

X{n,m}? X,至少 n 次,但是不超过 m 次

10)Possessive 数量词

X?+ X,一次或一次也没有

X*+ X,零次或多次

X++ X,一次或多次

X{n}+ X,恰好 n 次

X{n,}+ X,至少 n 次

X{n,m}+ X,至少 n 次,但是不超过 m 次

11)Logical 运算符

XY X 后跟 Y

X|Y X 或 Y

(X) X,作为捕获组

12)Back 引用

/n 任何匹配的 nth 捕获组

13)引用

/ Nothing,但是引用以下字符

/Q Nothing,但是引用所有字符,直到 /E

/E Nothing,但是结束从 /Q 开始的引用

14)特殊构造(非捕获)

(?:X) X,作为非捕获组

(?idmsux-idmsux)  Nothing,但是将匹配标志由 on 转为 off

(?idmsux-idmsux:X)   X,作为带有给定标志 on – off 的非捕获组

(?=X) X,通过零宽度的正 lookahead

(?!X) X,通过零宽度的负 lookahead

(?<=X) X,通过零宽度的正 lookbehind

(?<!X) X,通过零宽度的负 lookbehind

(?>X) X,作为独立的非捕获组

————————————————————————————————————————————————

作为一个例子,下面的每一个表达式都是合法的正则表达式,并且所有表达式都会成功匹配字符序列Rudolph。

第一个:Rudolph 注:就是单词本身,绝对匹配;

第二个:[rR]udolph 注:第一个字母可以在 r 和 R 中选择一个匹配,所以也能成功;

第三个:[rR][aeiou][a-z]ol.* 注:第一个字母在 r 和 R 中匹配,第二个字母在原音字母aeiou中匹配,第三个字母在a到z的26个字母中匹配,第四个字母和第五个字母被绝对匹配,后面的字符可以是任意的,因此这样的匹配也能成功;

第四个:R.* 注:第一个字母被绝对匹配,后面的字符可以是任意的匹配原则,所以也成功了。

在这个例子中遇到了一个.*的匹配符号,在这里我只解释:. 代表任何字符、* 代表任何字符即.可以出现零次或多次,这是一个非常常用的匹配符号,大家最好能够记住。

类似的,要想写出符合自己需求的正则表达式,可以参照构造类表对各类字符,以及匹配原则和方法的规定实现。

第三篇:正则表达式中的一个重要概念:量词

为 什么说量词是正则表达式中的一个重要的概念呢,如何有《Java编程思想》一书的同学可以看到,量词被放到了单独的一个章节进行了讲述,由此可见其一同一 般,主要是因为量词构造集在正则表示式的编写的时候是使用率非常平凡的构造集,也可以理解为是正则表达式的一个灵魂,所以要重视它的重要性。

量词,字面上的理解就是数量词,在正则表达式它又是被如何重新理解的呢?

在《Java编程思想》一书中的定义是:“量词描述了一个模式吸收输入文本的方式”,这里的方式被分为三种:贪婪的、勉强的、占有的。

通俗的解释可以是这样的:对一个字符或字符串在对出现次数上进行的限制和匹配。

在上面的构造集中也写出了这三种方式的匹配标准,这里就不做介绍了,对于这三种方式有什么区别,我给出《Java编程思想》一书做出的解释,大家可以根据自己的业务需要进行选择。

1)贪婪的。量词总是贪婪的,除非有其他的选项被设置。贪婪表达式会为所有可能的模式发现尽可能多的匹配。导致此问题的一个典型理由就是假定我们的模式仅能匹配第一个可能的字符组,如果它是贪婪的,那么它就会继续往下匹配。

2)勉强的。有问号来指定,这个量词匹配满足模式所需的最少字符数。因此也称作懒惰的,最少匹配的,非贪婪的、或不贪婪的。

3) 占有的。量词当前只有在JAVA语言中才可用(在其他语言中不可用),并且它也是更高级,因此我们大概不会立刻用到它。当正则表达式被应用于字符串时,它 会产生相当多的状态,以便在匹配失败时可以回溯。而占有的量词并不保存这些中间状态,因此我们可以防止回溯。它们常常由于防止正则表达式失控,因此可以使 正则表达式执行起来更有效。

注意点:在使用量词的时候,最好将要使用量词的字符或字符串有括号括起来;

第四篇:模式与匹配器

在介绍了一些正则表达式的基础之后,下面说说正则表达式在Java中是如何体现的,说的更明白一些也就是在Java中如何实现、如何编写代码。

在Java 中,正则表达式是通过java.util.regex包中的Pattern和Matcher两个类来实现的。一个Pattern对象表示一个正则表达式的 编译版本,可以做类似的对比,就好像是java文件和class文件,一个是让程序员看的,一个是让虚拟机执行的,在Java中一个正则表达式要转换为 Pattern对象才能最终被使用,Pattern的complie()方法可以实现,同时,我们可以使用matcher()方法和输入字符串从编译过的 Pattern对象中产生Matcher对象,在Matcher中可以得到你想要得到的处理完成以后的结果值的信息。

下来介绍Matcher类中的几个重要方法:

1)find():用户发现应用于CharSequence(即输入的字符串)的多重模式匹配,find()就像是一种迭代器,可以在输入字符串中向前移动迭代,在find()的第二版中,可以指定一个整型参数以告知要开始搜索的字符的位置;

2)groupCount():在介绍这个方法的之前,现介绍一个概念:“组”

组是由圆括号分开的多个正则表达式,随后可以根据它们的组号进行调用。第0组表示整个匹配表达式,第1组表示第一个用圆括号括起来的组,等等,因此,在表达式A(B(C))D中有三个组:第0组ABCD,第1组BC,第2组C。

groupCount()方法返回该模式中分组的数目。要注意的是第0组不包括在内。

3)group():返回由以前匹配操作所匹配的输入子序列。

4)group(int i):返回在以前匹配操作期间由给定组捕获的输入子序列。如果匹配成功,但是指定的组没有匹配输入字符串的任何部分,将返回null。

5)start(int group):返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引。

6)end(int group):返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。

7)start(): 返回以前匹配的初始索引。

8)end(): 返回最后匹配字符之后的偏移量。

模式标记:

模式标记是可以影响正则表达式的匹配行为的标记参数,为方便理解,列出这些标记的作用:

Pattern.CANON_EQ :启用规范等价。

Pattern.CASE_INSENSITIVE :启用不区分大小写的匹配。

Pattern.COMMENTS :模式中允许空白和注释。

Pattern.DOTALL :启用 dotall 模式,在dotall模式中,表达式.匹配多有字符,包括行终结符,缺省情况下,.表达式不匹配行终结符。

Pattern.LITERAL :启用模式的字面值分析。

Pattern.MULTILINE :启用多行模式。

Pattern.UNICODE_CASE :启用 Unicode 感知的大小写折叠。

Pattern.UNIX_LINES :启用 Unix 行模式。

替换操作:

替换操作在正则表达式中起了尤为重要的作用,能够实现替换操作的几个方法是:

1)replaceFirst(String replacement) :用replacement替换输入字符串中最先匹配的部分。

2)replaceAll(String replacement) :用replacement替换输入字符串中所有匹配的部分。

3) appendReplacement(StringBuffer sb, String replacement) :逐步的在sb中执行替换;而不是像replaceFirst()那样仅替换第一个匹配,或者像replaceAll()那样替换所有的匹配。这是个非常 重要的方法,因为它允许我们通过调用某些方法来执行一些其他处理来产生replacement(而不像replaceFirst()和 replaceAll()只能输入固定字符串)。有了这个方法,我们就可以通过编程来实现将目标拆分成组以及创建功能强大的替换。

4)appendTail(StringBuffer sb) :在一个或多个appendReplacement()调用之后被调用,以便复制输入字符串的剩余部分。

reset(String s)方法:

可以将Matcher对象应用于一个新的字符序列。

到 此为止,正则表达式在Java中的一般应用就差不多了,如果想要了解更多关于正则表达式在Java中的使用可以参考《Java编程思想》、 《Mastering Regular Expression(第二版)》,Jeffrey E.F.Friedl著(O’Reilly,2002)。

正则表达式的应用实例:

package Aaron;

import java.util.*;

import java.util.regex.*;

public class Main{


public Main(){


}


public static void main(String[] arg) {


main.emailMRE(”

lzq_3180@163.com

“);

main.replaceMRE(“3.23+4.34433-34433.3434″,”f”);

}

/**

* 验证email的正则表达式

* @param textStr String

*/

public void emailMRE(String textStr) {


String mre = “//w+@//w+[.]//w+”;

Pattern p = Pattern.compile(mre);

Matcher m = p.matcher(textStr);

if (m.find()) {


System.out.println(“验证成功!”);

} else {


System.out.println(“验证失败!”);

}

}

/**

* 将指定格式的字符串替换成要求的字符,本例中将表达式中的浮点数提取出来替换,

* 浮点数的精度要求为整数位1-8位,小数位1-8位

* 同时,将检索出的浮点数的位置在控制台输出

* @param textStr String

*/

public void replaceMRE(String textStr, String requestStr) {


String mre = “//d{1,8}[.]//d{1,8}”;

StringBuffer sb = new StringBuffer();

Pattern p = Pattern.compile(mre);

Matcher m = p.matcher(textStr);

int i = 1;

while (m.find()) {


System.out.println(“找到第” +i+ “个匹配:” + m.group()+ ” 位置为:” + m.start() + “-” + (m.end()-1));

m.appendReplacement(sb, requestStr);

i++;

}

m.appendTail(sb);

System.out.println(“替换后的结果字符串为:” + sb);

}

}

运行结果:

验证成功!

找到第1个匹配:3.23 位置为:0-3

找到第2个匹配:4.34433 位置为:5-11

找到第3个匹配:34433.3434 位置为:13-22

替换后的结果字符串为:f+f-f