正则表达式总结(Java描述)

江一帆 2020-03-02 PM 1848℃ 0条 4765字 Site load time is:152 ms 百度:已收录

基础

.   匹配除换行符之外的任意字符
\w  [a-zA-Z0-9_]
\W  [^a-zA-Z0-9_]
\d  [0-9]
\D  [^0-9] 
\s  匹配任意一位空白符(\n,\t等)
\S  匹配任意一位非空白符
^   匹配字符串的开始
$   匹配字符串的结束
\b  匹配一个单词的边界,即字与空格间的位置。
\B  匹配非单词边界

单词边界是单词和空格之间的位置。非单词边界是任何其他位置。
下面的表达式匹配单词 Chapter 的开头三个字符,因为这三个字符出现在单词边界后面:\\bCha

\b 字符的位置是非常重要的。如果它位于要匹配的字符串的开始,它在单词的开始处查找匹配项。
如果它位于字符串的结尾,它在单词的结尾处查找匹配项。
例如,下面的表达式匹配单词 Chapter 中的字符串 ter,因为它出现在单词边界的前面:ter\\b

下面的表达式匹配 Chapter 中的字符串 apt,但不匹配 aptitude 中的字符串 apt:\\Bapt
字符串 apt 出现在单词 Chapter 中的非单词边界处,但出现在单词 aptitude 中的单词边界处。
对于 \B 非单词边界运算符,位置并不重要,因为匹配不关心究竟是单词的开头还是结尾。

*     任意次   贪婪
?     0,1     非贪婪
+     >=1     贪婪
{n}   n   
{n,}  >=n     贪婪
{n,m} n~m     贪婪

在 *、+ 或 ? 限定符之后放置 ?,该表达式从"贪婪"表达式转换为"非贪婪"表达式或者最小匹配。
*?    任意次,尽可能少匹配
+?    >=1次,尽可能少匹配
??    0,1次,尽可能少匹配
*+    任意次,尽可能多匹配
.*?   如:a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab和ab。

进阶

断言

1.正向先行断言(正前瞻):
语法:(?=pattern)
作用:匹配pattern表达式的前面内容,不返回本身。

String reg="\\d+(?=</span>)";
String test = "<span class=\"read-count\">阅读数:641</span>";
Pattern pattern = Pattern.compile(reg);
Matcher mc=pattern.matcher(test);
while(mc.find()){
    System.out.println(mc.group(0));//641
}

2.正向后行断言(正后顾)
语法:(?<=pattern)
作用:匹配pattern表达式的后面的内容,不返回本身。

String reg="(?&lt;=&lt;span class=\"read-count\"&gt;阅读数:)\\d+";
String test = "&lt;span class=\"read-count\"&gt;阅读数:641&lt;/span&gt;";
Pattern pattern = Pattern.compile(reg);
Matcher mc=pattern.matcher(test);
while(mc.find()){
    System.out.println(mc.group(0));//641
}

3.负向先行断言(负前瞻)
语法:(?!pattern)
作用:匹配非pattern表达式的前面内容,不返回本身。

找到不是'的花朵'前面的祖国
String reg="祖国(?!的花朵)";
String test = "我爱祖国,我是祖国的花朵";
Pattern pattern = Pattern.compile(reg);
Matcher mc=pattern.matcher(test);
while(mc.find()){
    System.out.println(mc.group());//祖国
}

捕获

捕获组:匹配子表达式的内容,把匹配结果保存到内存中中数字编号或显示命名的组里,以深度优先进行编号,之后可以通过序号或名称来使用这些匹配结果。

1.数字编号捕获组:
语法:(exp)
解释:从表达式左侧开始,每出现一个左括号和它对应的右括号之间的内容为一个分组,
在分组中,第0组为整个表达式,第一组开始为分组。

String test = "020-85653333";
String reg="(0\\d{2})-(\\d{8})";
Pattern pattern = Pattern.compile(reg);
Matcher mc= pattern.matcher(test);
if(mc.find()){
    System.out.println("分组的个数有:"+mc.groupCount());
    for(int i=0;i&lt;=mc.groupCount();i++){
        System.out.println("第"+i+"个分组为:"+mc.group(i));
    }
}
分组的个数有:2
第0个分组为:020-85653333
第1个分组为:020
第2个分组为:85653333

2.命名编号捕获组:
语法:(?exp)
解释:分组的命名由表达式中的name指定

String test = "020-85653333";
String reg="(?&lt;quhao&gt;0\\d{2})-(?&lt;haoma&gt;\\d{8})";
Pattern pattern = Pattern.compile(reg);
Matcher mc= pattern.matcher(test);
if(mc.find()){
    System.out.println("分组的个数有:"+mc.groupCount());
    System.out.println(mc.group("quhao"));
    System.out.println(mc.group("haoma"));
}
分组的个数有:2
020
85653333

3.非捕获组:
语法:(?:exp)
解释:和捕获组刚好相反,它用来标识那些不需要捕获的分组,说的通俗一点,就是你可以根据需要去保存你的分组。

String test = "020-85653333";
String reg="(?:\0\d{2})-(\d{8})";
Pattern pattern = Pattern.compile(reg);
Matcher mc= pattern.matcher(test);
if(mc.find()){
    System.out.println("分组的个数有:"+mc.groupCount());
    for(int i=0;i&lt;=mc.groupCount();i++){
        System.out.println("第"+i+"个分组为:"+mc.group(i));
    }
}
分组的个数有:1
第0个分组为:020-85653333
第1个分组为:85653333

反向引用

反向引用需要使用到分组,分组就是使用()括起来的部分为一个整体,在进行分组匹配时的原则是:由外向内,由左向右
如:1,2等

      \1:表示的是引用第一次匹配到的()括起来的部分
      \2:表示的是引用第二次匹配到的()括起来的部分
1)例:
String regex = "^(\\d)\\1$";
首先这里是匹配两位,\d一位,\1又引用\d一位 这里的\1会去引用(\d)匹配到的内容,因为(\d)是第一次匹配到的内容。
如:str = "22"时,(\\d)匹配到2,所以\1引用(\\d)的值也为2,所以str="22"能匹配
    str = "23"时,(\\d)匹配到2,因为\1引用(\\d)的值2,而这里是3,所以str="23"不能匹配
         
2)例:
String regex = "^(\\d)\\1[0-9](\d)\1{2}";
注意在后面第二个(\d)\1{2}中的\1,这里的\1并不会去匹配他前面的(\d),而是匹配第一个(\\d),
如:第一个(\d)为3时,则第一个\1也为3,同样最后那个\1也为3,所以结果可以是335933,332533,而不是336444,339888

3)例:
String regex = "^(\d)\1[0-9](\d)\2{2}$";
这里使用了\2引用第二次匹配到的分组,这里第二次匹配的分组为\2前面的(\d),这里的{2}指的是\2的值出现两次
如:第一个(\d)为4时,\1引用第1个(\d)也为4,第二个(\d)为5时,\2引用第二个(\d)为5,所以结果可以是:447555,440222

4)例:
String regex = "^((\\d)3)\\1[0-9](\\d)\2{2}$";
当匹配中的分组有嵌套时,是从外向里匹配的,其次在由左向右匹配
这里主要是分析匹配到分组的顺序,首先匹配((\d)3)这整个部分,其次匹配((\d)3)里面的(\d),第三次匹配时最后一个\2前面的(\d)
如:如((\d)3)中的(\d)为2时,((\d)3)的值为23,此时\1为((\d)3)的值1,而\2引用((\d)3)中的(\d)的值3,第三个(\d)为5时,
此时\3引用第三个(\d)的值5,所以结果可以有:23238522,23230522

部分信息来源于:
你是如何学会正则表达式的?
正则表达式中的反向引用

标签: Java, 正则表达式

本文最后更新于:2020-03-05 13:20,可能因经年累月而与现状有所差异。

非特殊说明,本博所有文章均为博主原创。

评论啦~


召唤看板娘