[Study]Java 版正则表达式

Posted Spring-_-Bear

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Study]Java 版正则表达式相关的知识,希望对你有一定的参考价值。

文章目录

1. 入门案例

  1. 正则表达式的使用:根据指定的正则表达式规则,从给定的字符串中依次定位出满足匹配要求的子串

  2. Java 正则表达式的匹配原理:定位到子串时将子串首字符下标和尾字符下标 +1 记录到 matcher 对象的属性 int[] groups;group[0]group[1] 中以截取子串,同时记录 matcher 对象的属性 oldLast 的值为 group[1],下一次匹配从 oldLast 开始

  3. 匹配单个数字案例

    String content = "abc123qwe2tyu";
    // 匹配规则:单个数字
    String regExp = "\\\\d";
    // 模式对象
    Pattern pattern = Pattern.compile(regExp);
    // 匹配器对象
    Matcher matcher = pattern.matcher(content);
    // 循环匹配
    while (matcher.find()) 
        // matcher.group(0):return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString()
        System.out.println(matcher.group(0));
    
    

2. 分组

  1. 分组:在正则表达式中一对小括号表示一组,从 1 ······ n

    String regExp = "(\\\\d)(\\\\d)(\\\\d)(\\\\d)";
    
  2. 分组过后,matcher 对象的属性 groups 数组的第 0,1 个元素依然记录子串首字符下标,尾字符下标 +1;下标从 2 开始往后的 groups 数组的元素,每相邻两个元素依次记录该组首字符下标,尾字符下标 +1 的下标值。比如说 2020 出现在给定字符串的第 323 ~ 326 位置,我们将字符串分成两组,则有:

    groups[0] = 323、groups[1] = 327;
    groups[2] = 323、groups[3] = 325;
    groups[4] = 325、groups[5] = 327

3. 转义符

转义符 \\\\ : 在我们需要使用正则表达式去检索某些特殊字符的时候,需要用到转义符号,否则无法正确匹配。在 Java 的正则表达式中,两个 \\\\ 代表其它语言中的一个 \\ 。需要用到转义符的字符主要有以下几个:. * + ( ) $ / \\ ? [ ] ^

4. 选择匹配符

符号意义示例解释
|匹配 | 之前或之后的串ab|cdab 或 cd

5. 限定符

符号意义示例解释
*字符出现 0 次或 n 次(abc)*含有任意个 abc 的字符串
+字符出现 1 次或 n 次m+(abc)*至少 1 个 m 开头,后接任意个 abc
?字符出现 0 次或 1 次m+abc?至少一个 m 开头,后接 ab 或 abc
n指定长度[abcd]3abcd 中长度为 3 的子串
n,长度大于等于 n[abcd]3,abcd 中长度大于等于 3 的子串
n,m长度大于等于 n 小于等于 m[abcd]3,5abcd 中长度大于等于 3 小于等于 5 的子串

6. 定位符

符号意义示例解释
^指定起始字符^[0-9]+[a-z]至少 1 个数字开头,后接任意个小写字母
$指定结束字符^[0-9]\\ \\ -[a-z]+$至少 1 个数字开头,中间含有一个连接符,保证小写字母结尾
\\ \\b目标字符串边界han\\ \\b以字符串结尾或其后有空格,不需要括号
\\ \\B字符串非边界han\\ \\B字符串其后无空格或不是结尾字符串

7. 捕获分组

  1. 非命名分组

    String regExp = "(\\\\d\\\\d)(\\\\d)(\\\\d)";
    // matcher.group[0] = \\\\d\\\\d\\\\d\\\\d
    // matcher.group[1] = \\\\d\\\\d
    // matcher.group[2] = \\\\d
    // matcher.group[3] = \\\\d
    
  2. 命名分组:将匹配的子字符串捕获到一个组名称或编号名称中。name 不能包含任何标点符号且不能以数字开头

    // 可用单引号代替 regExp 中的尖括号
    String regExp = "(?<one>\\\\d\\\\d)(?<two>\\\\d\\\\d)";
    // matcher.group[0] = \\\\d\\\\d\\\\d\\\\d
    // matcher.group["one"] = \\\\d\\\\d
    // matcher.group["two"] = \\\\d\\\\d
    

8. 非捕获分组

不能使用 mather.group[1]matcher.group[2···] 获取结果

  1. “industr(?:y|ies)” <=> “industry|industries”
  2. “windows(?=95|98|2000)”:从 windows95 || windows98 || windows2000 中匹配出 windows
  3. “windows(?!95|98|2000)”:不从 windows95 || windows98 || windows2000 中匹配出 windows

9. 非贪婪匹配

Java 匹配模式默认贪婪匹配即尽量匹配长度较长的串。例如:str = aaaa; regExp = "\\\\ 3,4",则匹配结果为 aaaa

// 非贪婪匹配,匹配出长度尽可能短的字符串
String regExp = "1+?";

10. 匹配案例

符号意义示例解释
[ ]可接收的字符列表[efgh]e、f、g、h 中的一个字符
[^]不接收的字符列表[^abc]除 a、b、c 外的任意字符
-连字符A-Z任意单个大写字母
.除 \\n 以外的任意字符a…ba 开头,b 结尾,长度为 4 的字符串
\\ \\d[0-9]\\ \\d3(\\ \\d)?长度为 3 或 4 的数字字符串
\\ \\D[^0-9]\\ \\D(\\ \\d)*非数字开头,后接任意个数字字符
\\ \\w[0-9a-zA-Z_]\\ \\d3\\ \\w43 个数字字符开头长度为 7 的数字字母字符串
\\ \\W[^0-9a-zA-Z_]\\ \\W+\\ \\d2至少 1 个非数字字母开头,2个数字字符结尾
\\ \\s任何空白字符\\ \\d\\ \\ s \\ \\D数字字符开头,夹一个空白字符,非数字结尾
\\ \\S任何非空白字符\\ \\S匹配所有的非空白字符
// 字母不区分大小写的两种方式
String regExp = "(?i)abc";
Pattern pattern = Pattern.compile(regExp, Pattern.CASE_INSENSITIVE);
// 匹配基本汉字
String regExp = "[\\u4E00-\\u9FA5]";
// 匹配网址
String regExp = "(((https|http)?://)?([a-z0-9]+[.])|(www.))\\\\w+[.|\\\\/]([a-z0-9]0,)?[[.]([a-z0-9]0,)]+((/[\\\\S&&[^,;\\u4E00-\\u9FA5]]+)+)?([.][a-z0-9]0,+|/?)";

11. Pattern

// 整体匹配:判断传入的 content 内容是否符合 regExp 正则表达式要求
boolean isMatch = Pattern.matches(regExp,content);

12. Matcher

方法名功能
int start()返回匹配成功串的起始索引
int end()返回匹配成功串的结束索引 +1
String replaceAll(String)用参数替换正则表达式匹配到的字符串,并返回新字符串
/**
 * @author Spring-_-Bear
 * @version 2021-11-11 20:28
 */
public class RegExp 
    public static void main(String[] args) 
        String content = "hello hell hello";
        String regExp = "hello";

        Pattern pattern = Pattern.compile(regExp, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) 
            // 输出指定子串的开始下标和结束下标 +1
            System.out.println(matcher.start() + "\\t" + matcher.end());
        

        // 替换字符串:原字符串 content 保持不变
        String newString = matcher.replaceAll("李春雄");
        // Output:李春雄 hell 李春雄
        System.out.println(newString);
        // Output:hello hell hello
        System.out.println(content);
    

13. 反向引用

  1. 分组:我们可以用圆括号组成一个比较复杂的匹配模式,那么每个圆括号的部分我们可以看作是一个分组(也称为一个子表达式)

  2. 捕获:把正则表达式中分组匹配到的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用。从左往右,以分组的左括号为标志,第一个出现的分组的组号为 1,第二个为 2,以此类推。编号为 0 的组代表整个正则式

  3. 圆括号中的内容被捕获后,可以在这个括号后被使用,从而写出一个比较实用的匹配模式,我们称之为反向引用。这种引用既可以在正则表达式内部,也可以在正则表达式外部。正则表达式内部反向引用 \\\\ 分组号,正则表达式外部反向引用 $ 分组号

    // 匹配 2 个连续相同的数字
    String regExp = "(\\\\d)\\\\1";
    // 匹配 5 个连续相同的数字
    String regExp = "(\\\\d)\\\\14";
    // 匹配 4 位数的回文数,分别反向引用第 2 组,第 1 组
    String regExp = "(\\\\d)(\\\\d)\\\\2\\\\1";
    // 匹配类似 12321-333999111
    String regExp = "\\\\d5-(\\\\d)\\\\12(\\\\d)\\\\22(\\\\d)\\\\32";
    

14. 结巴去重

/**
 * 结巴去重
 *
 * @author Spring-_-Bear
 * @version 2021-11-11 20:28
 */
public class RegularExpression 
   public static void main(String[] args) 
       String content = "我...我...我...要要要..要要.学....Java!";

       // 1. 先替换调所有的 .
       String regExp = "\\\\.";
       Pattern pattern = Pattern.compile(regExp);
       Matcher matcher = pattern.matcher(content);
       content = matcher.replaceAll("");
       System.out.println(content);

       // 2. 匹配出重复的汉字,重复 1 到 n 次
       regExp = "(.)\\\\1+";
	   // content = Pattern.compile(regExp).matcher(content).replaceAll("$1");
       pattern = Pattern.compile(regExp);
       matcher = pattern.matcher(content);

       // 3. 反向引用分组中的内容替换正则表达式匹配到的内容:group[1] = "我" -> "我我我"
       content = matcher.replaceAll("$1");
       System.out.println(content);
   

15. String 中的 RegExp

  1. 替换功能:public String replaceAll(String regex,String replacement)
  2. 匹配功能:public boolean matches(String regex)
  3. 分割功能:public String[] split(String regex)

以上是关于[Study]Java 版正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式:如何匹配以括号“)”结尾的单词

42 python中正则中的分组 正则中匹配字符串的起始和结尾以及单词边界

java的正则表达

Java中的正则表达式

正则表达式特殊字符scrapy应用

正则表达式实现计算器