zoukankan      html  css  js  c++  java
  • Java 正则表达式

    JDK 中与正则表达式有关的类都在 java.util.regex 包中

    基本使用方法

    Pattern pattern = Pattern.compile("正则表达式"); //编译正则表达式
    Matcher matcher = pattern.matcher("目标字符串"); //绑定目标字符串
    //使用matcher对象进行具体的操作 ...

    正则匹配

    以下是 java.util.regex.Matcher 的部分源码,列举的都是与匹配操作相关的常用方法:

    public final class Matcher implements MatchResult {
    
        public boolean matches() {...} // 整体匹配
    
        public boolean lookingAt() {...} // 起始匹配
    
        public boolean find() {...} // 下一个匹配
    
        public boolean find(int start) {...} // 指定起始位置匹配
    
        public String group() { ... } // 获取匹配内容,等价于group(0);
    
        public String group(int group) { ... } // 获取分组编号为group的匹配内容
    
        public String group(String name) { ... } // 获取分组名为name的匹配内容
    
        public int groupCount() { ... } // 正则中共有多少个捕获分组
    
        ...
    
    }

    三类匹配操作

    1、整体匹配:matches() 

    等价于使用了位置匹配的元字符^和$,举个例子,给定正则"w",matches() 就相当于把给定的正则变成了"^w$"

    Pattern pattern = Pattern.compile("\w+"); // 匹配一个单词
    Matcher matcher1 = pattern.matcher("hello");
    System.out.println(matcher1.matches()); // true
    Matcher matcher2 = pattern.matcher("hello world");
    System.out.println(matcher2.matches()); // false

    2、起始匹配:lookingAt()

    等价于使用了位置匹配的元字符^,该方法相当于把"w"变成了"^w"

    Pattern pattern = Pattern.compile("\w+"); // 匹配一个单词
    Matcher matcher1 = pattern.matcher("hello");
    System.out.println(matcher1.lookingAt()); // true
    Matcher matcher2 = pattern.matcher(" hello");
    System.out.println(matcher2.lookingAt()); // false

    3、遍历匹配:find(); find(int start);

    一个正则表达式往往能在一段文本中匹配到多个结果,例如"w"能在"hello world"中匹配到两个结果:"hello"和"world"。

    如果把匹配结果 {"hello", "world"} 看作是一个 List<String> 集合,那么find(...)就类似于Java迭代器中的 hasNext();作用就是确定"正则表达式"能否在"目标字符串"中匹配到下一个结果。

    Pattern pattern = Pattern.compile("\w+"); // 匹配一个单词
    Matcher matcher = pattern.matcher("hello world");
    int result = 0;
    while (matcher.find()){
        result++;
    }
    System.out.println(result); // 2 

    获取匹配结果

    上面说的方法都是判断方法,其作用是判断"正则能否在目标文本中匹配到结果"。想得到匹配结果还需Matcher类中group(...)方法协助,在这之前,先说说"正则分组"的概念,再来说说group(...)。

    正则分组

    分组就是正则表达式中用小括号包围起来的部分,整个正则表达式是第一个分组,对应分组0,然后从左到右,顺序出现的小括号组就对应着分组1,2,3……(小括号出现顺序以左括号为准)。

    正则分组其实分为两种类型:捕获组、非捕获组。顾名思义,捕获组就是匹配的文本内容会被捕获并分组编号,非捕获组就是匹配的内容不会被捕获更不会被分组编号。非捕获组中的正则都是以?开头,但是以?开头的正则分组不一定就是非捕获组。

    这里只讨论捕获组,不讨论非捕获组。举个例子:

    正则:  (A(B(C)D))(EFG)
    分组0: (A(B(C)D))(EFG)
    分组1: (A(B(C)D))
    分组2: (B(C)D)
    分组3: (C)
    分组4: (EFG)

    group(...)

    无论是matches(); lookingAt(); find(); find(int start);这四个方法中的哪一个方法能够匹配成功,都可以调用group(...)获取结果。

    举一个例子,其它类推:

    Pattern pattern = Pattern.compile("(A(B(C)D))(EFG)"); // 匹配一个单词
    Matcher matcher = pattern.matcher("ABCDEFG");
    while (matcher.find()) {
        for (int i = 0; i < matcher.groupCount(); i++) {
            System.out.println("分组" + i + ": " + matcher.group(i));
        }
    }
    
    // 运行结果
    分组0: ABCDEFG
    分组1: ABCD
    分组2: BCD
    分组3: C 

    正则替换

    public final class Matcher implements MatchResult {
    
        public static String quoteReplacement(String s) { ... } // 特殊字符替换成字面值常量
    
        public Matcher appendReplacement(StringBuffer sb, String replacement) { ... } // 渐进式替换
    
        public StringBuffer appendTail(StringBuffer sb) { ... } // 执行完appendReplacement方法后,可追加剩余字符串到最终结果
    
        public String replaceAll(String replacement) { ... } // 替换所有匹配结果
    
        public String replaceFirst(String replacement) { ... } // 替换第一个匹配结果
    
        ...
    
    }

    1、quoteReplacement(String s); 该方法是将特殊字符""和"$"替换成字面值常量,用到的机会很少。

    ""是转译字符

    "$"在appendReplacement(sb,replacement)方法的replacement参数中可以表示分组(如$0表示分组0,$1表示分组1……)

    举个例子(代码跑不起来):

    public static void main(String[] args) throws IOException {
        String string = "Our days have bloomed";
        StringBuffer sbuf = new StringBuffer();
        Pattern compile = Pattern.compile("[aeiou]");
        Matcher matcher = compile.matcher(string);
        while (matcher.find()) {
            // 1和2等价
            matcher.appendReplacement(sbuf, Matcher.quoteReplacement("\")); // 1
            matcher.appendReplacement(sbuf, "\\"); // 2
            // $0表示匹配到的文本分组0的内容
            matcher.appendReplacement(sbuf, "$0-index");// 3
        }
        matcher.appendTail(sbuf);
        System.out.println(sbuf);
    } 

    2、replaceAll(String replacement)和replaceFirst(String replacement)这两个方法在String类中也有,结果是一样的。可根据实际情况选择使用,如果只会调用一次,建议使用String类自带的方法,效率会更高些,也避免了编译Pattern的开销。

    public static void main(String[] args) throws IOException {
        String string = "Our days have bloomed";
    
        Pattern pattern = Pattern.compile("[aeiou]");
        Matcher matcher = pattern.matcher(string);
    
        String replace = matcher.replaceFirst("*");
        System.out.println(replace);// O*r days have bloomed
        replace = string.replaceFirst("[aeiou]", "*");
        System.out.println(replace);// O*r days have bloomed
    
        replace = matcher.replaceAll("*");
        System.out.println(replace); // O*r d*ys h*v* bl**m*d
        replace = string.replaceAll("[aeiou]", "*");
        System.out.println(replace);// O*r d*ys h*v* bl**m*d
    }

    3、appendReplacement(StringBuffer sb, String replacement)和appendTail(StringBuffer sb)这两个方法通常都是结合着使用,执行渐进式替换操作,就是正则分组替换的过程可控,不会像上面的两个方法,只能使用一个固定的字符串。

    public static void main(String[] args) throws IOException {
        String string = "Our days have bloomed";
        StringBuffer sbuf = new StringBuffer();
        Pattern compile = Pattern.compile("[aeiou]");
        Matcher matcher = compile.matcher(string);
        while (matcher.find()) {
            matcher.appendReplacement(sbuf, matcher.group().toUpperCase());
        }
        matcher.appendTail(sbuf);
        System.out.println(sbuf);
    }
    
    // 结果:OUr dAys hAvE blOOmEd
  • 相关阅读:
    [毕业设计]多文档自动摘要.面向灾害事件
    windows,无法启动承载网络,解决办法
    【现代程序设计】【期末作业】【homework-09】
    ColorNote.疑难解答
    【现代程序设计】【homework-08】
    【现代程序设计】【homework-07】
    【现代程序设计】【homework-05】
    【现代程序设计】【homework-04】
    homework-10
    homework-06&homework-09
  • 原文地址:https://www.cnblogs.com/litmmp/p/5361610.html
Copyright © 2011-2022 走看看