Pattern类(java.util.regex.Pattern)
Pattern是一个不可变类且线程安全。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。
// 直接调用 Pattern 类中的静态boolean类型的方法 matches 判断
// 如果一个模式多次被使用,编译一次并重用它将比每次调用此方法更有效
System.out.println(Pattern.matches("a*b", "aab")); // true
System.out.println(Pattern.compile("a*b").matcher("aab").matches()); // 表现方式同上
// 经典写法
Pattern p = Pattern.compile("a*b"); //通过静态方法创建 Pattern 对象
Matcher m = p.matcher("aab");
System.out.println(m.matches()); // true
System.out.println(p.pattern()); // a*b 返回编译此模式的正则表达式
System.out.println(p.flags()); // 0 返回此模式的匹配标志
String [] s = p.split("adbcacbfaob");
String [] s1 = p.split("adbcacbfaob",2);
Stream<String> s2 = p.splitAsStream("adbcacbfaob");
System.out.println(Arrays.toString(s)); // [ad, cac, fao] 将给定的输入序列分成这个模式的匹配
System.out.println(Arrays.toString(s1)); // [ad, cacbfaob]
System.out.println(s2.count()); // 返回该流中的元素个数
// 指定过滤模式
Pattern p1 = Pattern.compile("a\d+?b", Pattern.CASE_INSENSITIVE); // 等同于(?i)a\d+?b
System.out.println(p1.matcher("A12412B").matches()); // true 不区分大小写匹配
Matcher类(java.util.regex.Matcher)
Matcher也是一个不可变类. 通过调用Pattern的matcher方法创建匹配器。可以使匹配执行三种不同的匹配操作:
- matches 将整个输入序列与该模式匹配
- lookingAt 将输入序列从头开始于该模式匹配
- find 扫描输入序列以查找该模式匹配的下一个子序列
String t = "a1test2A34test4";
Pattern p = Pattern.compile("(?i)a\d+?"); // 忽略大小写匹配以a开头且尽可能少的数字字符
Matcher m = p.matcher(t);
// 遍历匹配到的字符串
while(m.find()){
System.out.println("find: start:"+m.start() +" end:" +m.end() +" group:"+m.group());
//find: start:0 end:2 group:a1
//find: start:7 end:9 group:A3
}
System.out.println(m.find()); // false 遍历完后,再次查找返回false
// 通过查找匹配的字符的偏移量,来确定是否匹配
System.out.println(m.matches()); // false 匹配整个字符串
try { // 因为没有匹配到字符串,所以会抛出异常
System.out.println("matches: start:" + m.start() + " end:" + m.end());
}catch(Exception e){
System.out.println(e.getMessage()); //No match available (java.lang.IllegalStateException:)
}
System.out.println(m.lookingAt());// true 从头开始匹配
System.out.println("lookingAt: start:"+m.start()+" end:"+m.end()+" group:"+m.group());//lookingAt: start:0 end:2 group:a1
System.out.println(m.find()); // true 匹配下一个子序列,这里返回的是最后一个匹配
System.out.println("find: start:"+m.start() +" end:" +m.end() +" group:"+m.group()); // find: start:7 end:9 group:A3
System.out.println(m.find()); // false 已经全部查找完成
以上是三种匹配方式。有时候我们需要对字符串或文本进行替换,那Matcher类有没有提供相应的方法呢?也提供了几种替换的方法
- replaceFirst 将匹配第一个子序列替换为给定的字符串
- replaceAll 将匹配每个子序列替换为给定的字符串
- appendReplacement和appendTail 实现非终端和终端的添加和替换步骤
// 替换字符串
Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString()); // one dog two dogs in the yard
System.out.println(m.replaceAll("pig")); // one pig two pigs in the yard
System.out.println(m.replaceFirst("monkey")); // one monkey two cats in the yard
Matcher类中还有其他,如重置匹配器,指定匹配范围等。这里示范重置匹配器、组别相关的方法
String t = "a1test2A34test4";
Pattern p = Pattern.compile("(?i)(a\d+)([a-z]+)(\d)(a\d+?)(\d)([a-z]+)(\d)");
Matcher m = p.matcher(t);
Matcher newM = m.reset("a1test2A36LTest4");
System.out.println(newM.groupCount()); // 7 组(不包括group(0))
if(m.find()){
System.out.println(newM.group(1)); // a1
System.out.println(newM.group(2)); // test
System.out.println(newM.group(3)); // 2
System.out.println(newM.group(4)); // A3
System.out.println(newM.group(5)); // 6
System.out.println(newM.group(6)); // LTest
System.out.println(newM.group(7)); // 4
System.out.println(newM.group(0)); // 匹配 a1test2A36LTest4
/*
for(int i=0;i<newM.groupCount();i++) {
System.out.println(newM.group(i));
}*/
}else{
System.out.println("---");
}
正则表达式语法
正则表达式,又称规则表达式,通常被用来检索、替换那些符合某个模式(规则)的文本。它并不仅限于某一种语言,但是在每种语言中有细微的差别。
字符 | 说明 |
---|---|
将下一字符标记为特殊字符、文本、反向引用或八进制转义符 | |
^ | 匹配字符串开始的位置 |
$ | 匹配字符串结尾的位置 |
. | 匹配任意单个字符(" "除外) |
* | 重复零次或多次匹配前面的字符或子表达式, 等效{0, } |
+ | 一次或多次,等效{1, } |
? | 零次或一次,等效{0,1} |
{n} | 重复n次 |
{n, } | 至少匹配n次或匹配多次 |
{n, m} | 至少匹配n次或至多匹配多次 |
x|y | 匹配x 或y |
[a-z] | 匹配指定范围内的任何字符. 指定字符[abc],不匹配包含的字符[^abc] |
[0-9] | 匹配指定范围内的任何数字. 指定字数[123],不匹配包含的数字[^123] |
匹配一个字边界,字与空格间的位置 | |
B | 非字边界匹配 |
d | 数字字符匹配. 等效于 [0-9] |
D | 非数字字符匹配. 等效于 [^0-9] |
w | 匹配任何字类字符,包括下划线. 等效[A-Za-z0-9_] |
W | 与任何非单词字符匹配. 等效[^A-Za-z0-9_] |
s | 匹配任何空白字符,包括空格、制表符、换页符等. 等效 [ f v] |
S | 匹配任何非空白字符. 等效[^ f v] |
(pattern) | 匹配pattern并捕获该匹配的子表达 |
(?:pattern) | 匹配pattern但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配 |
(?=pattern) | 执行正向预测先行搜索的子表达式,该表达式匹配处于匹pattern 的字符串的起始点的字符串.它是一个非捕获匹配,即不能捕获供以后使用的匹配 |
(?!pattern) | 执行反向预测先行搜索的子表达式,该表达式匹配不处于匹pattern 的字符串的起始点的搜索字符串.它是一个非捕获匹配,即不能捕获供以后使用的匹配 |
(?i) | 表示忽略大小写(仅匹配US-ASCII字符集中的字符), 等效 Pattern.CASE_INSENSITIVE |
(?x) | 表示允许空格和注释格式,将忽略空格,并且以#开头的嵌入式注释将被忽略,直到行尾, 等效Pattern.COMMENTS |
(?m) | 表示启用多行模式, 表达式^和$分别匹配行终止符或输入序列的结尾, 等效Pattern.MULTILINE |
(?s) | 表示启用单行模式, 表达式.匹配任何字符,包括行终止符。 默认情况下,此表达式与行终止符不匹配, 等效Pattern.DOTALL |
(?u) | 启用 Unicode 感知的大小写折叠, 不区分大小写的匹配(由CASE_INSENSITIVE标志启用)以与Unicode标准一致的方式完成. 默认情况下,不区分大小写的匹配假定仅匹配US-ASCII字符集中的字符, 等效Pattern.UNICODE_CASE |
注:使用正则的时候需要注意,在java中的反斜杠( )需要进行转义.
正则表达式实例
- IP地址匹配:
^(?:(?:1[0-9][0-9].)|(?:2[0-4][0-9].)|(?:25[0-5].)|(?:[1-9][0-9].)|(?:[0-9].)){3}(?:(?:1[0-9][0-9])|(?:2[0-4][0-9])|(?:25[0-5])|(?:[1-9][0-9])|(?:[0-9]))$
((?:(?:25[0-5]|2[0-4]d|[01]?d?d)\.){3}(?:25[0-5]|2[0-4]d|[01]?d?d))
- 身份证匹配:
(^d{15}$)|(^d{18}$)|(^d{17}(d|X|x)$)
^(d{6})(d{4})(d{2})(d{2})(d{3})([0-9]|X)$
- 网址URL匹配:
[a-zA-z]+://[^s]*
^http://([w-]+.)+[w-]+(/[w-./?%&=]*)?$
- 邮箱地址匹配:
^w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$
^[a-z]([a-z0-9]*[-_]?[a-z0-9]+)*@([a-z0-9]*[-_]?[a-z0-9]+)+[.][a-z]{2,3}([.][a-z]{2})?$
注:
正则相关教程:https://www.oschina.net/question/12_9507
正则相关实例:https://c.runoob.com/front-end/854
正则匹配工具下载
正则在线工具