Java_正则表达式

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("---");
 }

正则表达式语法

正则表达式,又称规则表达式,通常被用来检索、替换那些符合某个模式(规则)的文本。它并不仅限于某一种语言,但是在每种语言中有细微的差别。

字符 说明
\ 将下一字符标记为特殊字符、文本、反向引用或八进制转义符
^ 匹配字符串开始的位置
$ 匹配字符串结尾的位置
. 匹配任意单个字符("\r\n"除外)
* 重复零次或多次匹配前面的字符或子表达式, 等效
+ 一次或多次,等效
? 零次或一次,等效
重复n次
至少匹配n次或匹配多次
至少匹配n次或至多匹配多次
x|y 匹配x 或y
[a-z] 匹配指定范围内的任何字符. 指定字符[abc],不匹配包含的字符[^abc]
[0-9] 匹配指定范围内的任何数字. 指定字数[123],不匹配包含的数字[^123]
\b 匹配一个字边界,字与空格间的位置
\B 非字边界匹配
\d 数字字符匹配. 等效于 [0-9]
\D 非数字字符匹配. 等效于 [^0-9]
\w 匹配任何字类字符,包括下划线. 等效[A-Za-z0-9_]
\W 与任何非单词字符匹配. 等效[^A-Za-z0-9_]
\s 匹配任何空白字符,包括空格、制表符、换页符等. 等效 [ \f\n\r\t\v]
\S 匹配任何非空白字符. 等效[^ \f\n\r\t\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
正则匹配工具下载
正则在线工具

posted @ 2018-08-13 22:26  zeotoone  阅读(194)  评论(0编辑  收藏  举报