Java正则表达式

    Java正则表达式主要由两个类来实现:

java.util.regex.Pattern
java.util.regex.Matcher
    Pattern用来将一个字符串形式的正则表达式编译成一个Pattern对象。Matcher执行匹配操作,解释模式串返回是否匹配目标字符串。典型使用方式如下:

Pattern p = Pattern.compile(“a*b”);
Matcher m = p.matcher(str);
boolean b = m.matches();

1.      构造正则表达式

  字符

x

字符x

\\

反斜杠

\0n

匹配8进制数0n

\xhh

匹配16进制数0xhh

\t

制表符Tab

\n

换行符

\r

回车

\f

换页

\a

响铃

\e

转义

\cx

与x对应的控制字符

  注意\\表示java正则表达式的反斜杠,如果要匹配反斜杠字符则需要\\\\。即

String str = "\\";
String regex = "\\\\";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
boolean ret = matcher.matches();
System.out.println(ret);

    输出true。

    字符类

[abc]

abc中的任意一个字符

[^abc]

除abc之外的任意一个字符(否定)

[a-zA-Z]

从a到z或从A到Z的任意一个字符(并集)

[a-d[m-p]]

从a到d或从m到p的任意一个字符(并集)

[a-z&&[def]]

def中的任意一个字符(交集)

[a-z&&[^bc]]

从a到z,除去b到c

[a-z&&[^m-p]]

从a到z,除去m到p

    预定义字符类

.

任意字符

\d

数字:[0-9]

\D

非数字:[^0-9]

\h

水平空白符

\H

非水平空白符[^\h]

\s

空白符(空格、Tab、换行、换页和回车)

\S

非空白符[^\s]

\v

垂直空白符

\V

非垂直空白符[^\v]

\w

词字符[a-zA-Z_0-9]

\W

非词字符[^\w]

    边界匹配

^

行的起始

$

行的结束

\b

词的边界

\B

非词的边界

    逻辑操作

XY

X后面跟着Y

X|Y

X或Y

(X)

捕获X,在一个组中捕获

    组是用括号划分的,正则表达式的每个组都有一个编号,从左向右每遇到一个左括号则找到一个组,组的编号依次加1。如正则表达式((A)(B(C))),第1组是((A)(B(C))),第2组是(A),第3组是(B(C)),第4组是(C)。第0组总是表示整个正则表达式。
    量词

X?

X重复0次或1次

X*

X重复0次或多次

X+

X重复1次或多次

X{n} X{n,} X{n,m}

X重复n次,X至少重复n次,X重复n到m次

    量词后缀

?

设默认(贪婪)匹配为reluctant匹配

+

设默认(贪婪)匹配为possessive匹配

    Java在默认情况下,量词总是在匹配成功前提下匹配尽可能多的字符,称为贪婪匹配。后缀?改变为reluctant匹配,即在匹配成功前提下匹配尽可能少的字符。后缀+改变为possessive匹配,即使匹配失败也要匹配尽可能多的字符。

     如模式(ab)*ab能匹配ababab,在能匹配成功的前提下,(ab)*匹配了abab,这里只有一种匹配方式,所以(ab)*?ab与(ab)*ab效果相同,但是(ab)*+ab就不能匹配ababab了,(ab)*+为possessive匹配,尽可能多的字符,直接匹配了ababab整个串,(ab)*+后面的ab没有与之匹配的字符了,匹配失败。

2.      正则表达式使用

编译模式串

    模式串使用compile函数编译得到Pattern,表示模式串,可以指定一些标识:

staticPattern compile(String regex, int flags);

Pattern.CASE_INSENSITIVE(?i)  :  匹配时忽略大小写的区别,如果对Unicode字符忽略大小写,需要将该标识与UNICODE_CASE结合使用。

Pattern.MULTILINE(?m)  :  默认情况下^和$匹配字符串的开始和结束,这种模式下,^和$既匹配一行的开始和结束,也匹配字符串的开始和结束。

Pattern.COMMENTS(?x)  :  忽略正则表达式里的空白符(空格、Tab、回车),注释从#开始,一直到这行结束。

Pattern.UNIX_LINES(?d)  :  \n被认为是一行结束。

匹配操作

    Matcher类将模式串与目标串进行匹配。调用Pattern的matcher函数即可得到Matcher对象:

Pattern pattern = Pattern.compile(regex);	// regex是模式串
Matcher matcher = pattern.matcher(str);	// str是目标串
    Matcher提供3个方法进行匹配操作:
boolean matches()
boolean lookingAt()
boolean find()
boolean find(int start)
    函数返回布尔值,表示是否匹配成功。matches是将模式串匹配整个目标串,lookingAt是从目标串的起始位置开始匹配,不一定要匹配整个目标串。find函数找到一个匹配的子串即可,start参数指定开始匹配的位置,反复调用find可以得到所有匹配子串。应用中find函数使用较多。
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegularExpress {

	public static void main(String[] args) {
		String str = "a23opA23";
		
		String regex = "a[0-9]*[a-z]+[A-Z]";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(str);
		boolean bMatches = matcher.matches();
		matcher.reset();
		boolean bLookingAt = matcher.lookingAt();
		matcher.reset();
		boolean bFind = matcher.find();
		System.out.println("bMatches = " + bMatches + ", bLookingAt = " + bLookingAt + ", bFind = " + bFind);
	}
}
    运行结果为:

bMatches = false, bLookingAt = true, bFind = true
    模式串 "a[0-9]*[a-z]+[A-Z]"不能匹配 "a23opA23",所以matches返回false,但是该模式串能匹配 "a23opA23"的子串 "a23opA",lookingAt和find返回true。

    使用find可以找到目标串中所有匹配的子串:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegularExpressFind {

	public static void main(String[] args) {
		String str = "It's a good day.";
		String regex = "\\w+";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(str);
		while(matcher.find()) {
			System.out.println(matcher.group());
		}
	}
}
    运行结果为:
It
s
a
good
day

    "\\w+"是指一个或多个词字符(a-zA-Z_0-9),因此该程序将输入字符串拆分为一个个单词,去掉了非词字符。

Region

     匹配时还可以指定目标串的区域,区域是目标串的一个区间,所有匹配操作在该区间上进行,默认情况下是区域是整个目标串。

Matcher region(int start, int end);
int regionStart();
int regionEnd();
    区域不是说模式串要匹配到多少目标串才算成功(这是由matches、lookingAt、find三个函数实现),而是重新设定目标串的范围。如目标串abcdef的默认区域是(start=0,end=6),如果设定为(start=1,end=5)则表示只在子串bcde上进行匹配。感觉没什么用,如果需要,直接将输入串构造一个子串就可以了,当然如果输入的CharSequence是String,会有效率问题吧。

Groups

    上面已经说过组的概念。如果模式串中有小括号,即模式串中有组,每次匹配之后不仅可以找到整个模式串匹配的目标子串,还可以找到模式串中每个组此时匹配的目标子串。主要有以下几个函数:

String group()		// 返回上次匹配之后,模式串匹配的目标子串
String group(int group)	// 返回上次匹配之后,模式串中指定组匹配的目标子串
int groupCount()	// 返回模式串中组的数目
int start()		// 返回上次匹配之后,匹配的目标子串起始位置
int start(int group)	// 返回上次匹配之后,指定组匹配的目标子串的起始位置
int end()		// 返回上次匹配之后,匹配的目标子串的结束位置
int end(int group)	// 返回上次匹配之后,指定组匹配的目标子串的结束位置
    注意这里的下标是左闭右开区间,结束位置是目标子串最后一个字符的下一个位置。group的下标是从1开始的,调用group(0)与调用group()效果相同,都表示整个正则表达式的匹配结果,start和end函数也是一样。先用matches匹配函数实验一下:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegularExpressGroup1 {

	public static void main(String[] args) {
		String str = "abce1234";
		String regex = "([a-z]*(e))[0-9]*";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(str);
		System.out.println("group count = " + matcher.groupCount());
		if(matcher.matches()) {
			for(int i=0; i<=matcher.groupCount(); i++) {
				System.out.print("[" + matcher.group(i) + "]");
				System.out.println();
			}
		}
	}
}
    运行结果为:

group count = 2
[abce1234]
[abce]
[e]

    模式串"([a-z]*(e))[0-9]*"的组数显然是2。matches如果匹配成功,group(0)显然是整个目标串。第1组([a-z]*(e))匹配的是abce,第2组(e)匹配的是e。

    下面的例子使用find匹配函数:
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegularExpressGroup2 {

	static public final String POEM = "Twas brillig, and the slithy toves\n" +
			"Did gyre and gimble in the wabe.\n" +
			"All mimsy were the borogoves,\n" + 
			"And the mome raths outgrabe.\n\n" +
			"Beware the Jabberwock, my son,\n" +
			"The jaws that bite, the claws that catch.\n" +
			"Beware the Jubjub bird, and shun\n" +
			"The frumious Bandersnatch.";
	
	public static void main(String[] args) {
		Matcher m = Pattern.compile("(?m)(\\S+)\\s+((\\S+)\\s+(\\S+))$").matcher(POEM);
		while(m.find()) {
			for(int j=0; j<=m.groupCount(); j++)
				System.out.print("[" + m.group(j) + "]");
			System.out.println();
		}
	}
}
    运行结果为:
[the slithy toves][the][slithy toves][slithy][toves]
[in the wabe.][in][the wabe.][the][wabe.]
[were the borogoves,][were][the borogoves,][the][borogoves,]
[mome raths outgrabe.][mome][raths outgrabe.][raths][outgrabe.]
[Jabberwock, my son,][Jabberwock,][my son,][my][son,]
[claws that catch.][claws][that catch.][that][catch.]
[bird, and shun][bird,][and shun][and][shun]
[The frumious Bandersnatch.][The][frumious Bandersnatch.][frumious][Bandersnatch.]
    模式串中的(?m)指定Pattern.MULTILINE标识,^和$也匹配一行的开始和结束。\\s+匹配一个或多个空白符,\\S+匹配一个或多个非空白符。所以模式串 "(?m)(\\S+)\\s+((\\S+)\\s+(\\S+))$"匹配每行末尾的三个非空白符子串,中间有两段空白符。第1组 (\\S+)匹配每行倒数第三个非空白子串;第2组 ((\\S+)\\s+(\\S+))匹配每行末尾两个非空白符子串,中间有一段空白符;第三组 (\\S+)匹配每行倒数第二个非空白子串;第四组 (\\S+)匹配每行最后一个非空白子串。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值