您的位置:首页 > 编程语言 > Java开发

Java正则表达式

2016-06-16 20:05 375 查看
参考:

- 《Java编程思想》

- http://deerchao.net/tutorials/regex/regex-1.htm

正则表达式基础

字符类

.任意字符

[abc]包含abc的任意字符

[^abc] 除了abc之外的任何字符(否定)

\s空白符(空格,tab,换行,换页,回车)

\S 非空白符,即[^\s]

\d 数字[0-9]

\D 非数字[^0-9]

\w 词字符[a-zA-Z0-9]

\W 非词字符[^\w]

量词

(*) 重复0次或多次

(+) 重复1次或多次(不加括号显示有问题==)

? 重复0次或1次

{n} 重复n次

{n,} 至少重复n次

{n,m} 至少重复n次且至多重复m次

边界匹配符

^ 字符串的开始(多行模式下为一行的开始)

$ 字符串的结束(多行模式下为一行的结束)

\b 词的边界

\B 非词的边界

\G 前一个匹配的结束

逻辑操作符

a-z&&[hij] 交集

a|b 并集

(X) 捕获组

贪婪和懒惰

量词总是贪婪的,除非有其他选项被设置。

贪婪匹配总会匹配尽可能多的字符。

懒惰匹配总会匹配尽可能少的字符。

示例

String: aabab

贪婪匹配:

regex: a.*b

ans: aabab

非贪婪匹配:

regex: a.*?

ans: aab ab

懒惰量词

*? 重复0次或多次,但尽可能少重复

+? 重复1次或多次,但尽可能少重复

?? 重复0次或1次,但尽可能少重复

{n,m}? 重复n到m次,但尽可能少重复

{n,}? 重复n次以上,但尽可能少重复

位置指定

只匹配一个位置,并不占用字符。

- 零宽先行断言 (?=exp) 匹配后缀为exp的部分,不包括exp

- 零宽后行断言 (?>=exp) 匹配前缀为exp的部分,不包括exp

- 零宽负向先行断言 (?!exp) 匹配后缀exp不存在的位置

- 零宽负向后行断言 (?>!exp) 匹配前缀exp不存在的位置

示例

(?<=\s)\d+(?=\s) 匹配以空白符间隔的数字(不包括空白符)。

\d{3}(?!\d) 匹配三位数字,而且这三位数字的后面不能是数字。

(?

Java正则表达式对象

Pattern

Matcher

public static void main(String[] args) {
String string = "This is a test";
Pattern pattern = Pattern.compile("\\w*is\\w*");
Matcher matcher = pattern.matcher(string);
while(matcher.find()){
System.out.println("find() '" + matcher.group() + "' start = " + matcher.start() + ", end = "+matcher.end());
}
}


重要的方法

boolean matcher.find()

可以用来查找多个匹配,像迭代器那样遍历字符串。

String matcher.group()

组是用括号划分的正则表达式,组号为0表示整个表达式,组号为1表示第一对括号括起的组(从外向内),依次类推。

boolean matcher.lookingAt()

用来判断该字符串的开始部分(不必须是全部)是否能够匹配模式。

boolean matcher.matches()

用来判断整个字符串是否匹配正则表达式模式。

int matcher.start()/end()

start()方法返回先前匹配的起始位置的索引,end()方法返回所匹配的最后字符的索引加1的值。

Matcher matcher.reset()

不带参数:可以将Matcher对象重新设置到当前字符序列的起始位置(matcher.reset());

带字符串参数:将现有的Matcher对象应用于一个新的字符序列(matcher.reset(“I am a new string.”))

others

可以复习下String的split()方法和replace()/replaceFirst()/replaceAll()等方法。

Pattern标记

Pattern类的compile()方法还有另外一个版本,它接受一个标记参数,以调整匹配的行为:

Pattern pattern.compile(String regex, int flag)


其中的flag都是Pattern类中的常量,常用的几个:

Pattern.CASE_INSENSITIVE

或者在regex的开头加上(?i) 。

这个标记允许模式匹配不必考虑大小写。

Pattern.COMMENTS

或者在regex的开头加上(?x) 。

在这种模式下,空格符将被忽略掉,并且以#开始直到行末的注释也会忽略掉。

Pattern.MULTILINE

或者在regex的开头加上(?m) 。

在多行模式下,表达式^和$分别表示一行的开始和结束(默认只是字符串的开始和结束)。

Pattern.DOTALL

或者在regex的开头加上(?s) 。

在此模式下,表达式’.’匹配所有字符,包括行终结符。默认情况下不匹配行终结符。

正则表达式扫描输入

在默认的情况下,Scanner 根据空白字符对输入进行分词,但是可以用正则表达式指定自己所需的定界符:

scanner.useDelimeter("\\s*,,\\s*"); //指定定界符
Pattern pattern = scanner.delimeter(); //返回当前作为定界符的pattern对象


在这里遇到了一个问题:

public static void main(String[] args) {
Scanner scanner = new Scanner("1,2,3,4");
scanner.useDelimiter("\\s*,\\s*");
while(scanner.hasNextInt())
System.out.println(scanner.nextInt());
}


输出:

1

2

3

4

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
scanner.useDelimiter("\\s*,\\s*");
while(scanner.hasNextInt())
System.out.println(scanner.nextInt());
}


输入:

1,2,3,4

输出:

1

2

3

后来在Stack Overflow上发现有人跟我有同样的疑问,这是因为在控制台输入时,程序在发现定界符之前没有办法判断你是否结束输入(字符串作为Scanner的输入对象时,程序能够判断是否到达字符串结尾),所以产生了上述区别。通常将System.in作为Scanner的输入对象时,将整行读进来,然后再split():

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
String inputString = scanner.nextLine();
String[] outputStrings = inputString.split("\\s*,\\s*");
System.out.println(Arrays.toString(outputStrings));
}
}


输入:

1,2,3,4

输出:

[1, 2, 3, 4]

或者将正则表达式改为”\s*[,|\n]\s*”,则能够从控制台获取最后输入值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: