java&正则表达式(Pattern类和Matcher类)

文章目录

前言

正则表达式(regex): 是一个字符串,由字面值字符和特殊符号组成,是用来描述匹配一个字符串集合的模式,可以用来匹配、替换和拆分字符串。

见鉴文章:

https://blog.csdn.net/xuemoyao/article/details/8033138

测试:

菜鸟工具中的正则表达式测试
https://c.runoob.com

一、Java中使用正则表达式

注:如果对正则表达式不熟悉的可以看第二部分的正则表达式相关语法,然后再来看这一块内容

①捕获组

捕获组的概念在java中使用正则表达式是比较重要的,我们可以通过java中的matcher对象来获得捕获组中的内容,继而获得我们需要通过正则表达式获取的内容。

1、 捕获组是把多个字符当成一个单独单元进行处理的方法,它通过对括号内的字符分组来创建,捕获组通过从左到右计算其括号来编号,如下所示

正则表达式:
((A)(B(C))) 

从左到右对应四个捕获组:
((A)(B(C)))
(A)
(B(C))
(C)

2、 捕获组可以通过调用matcher对象的groupCount方法来查看表达式有多少个分组。(groupCount方法返回一个int值,来表示matcher对象当前有多少个捕获组)

3、还有一个特殊的组零(group(0)),它代表整个表达式。(该组不包括在groupCount的返回值中)

4、以 (?) 开头的组是纯的非捕获 组,它不捕获文本,也不针对组合计进行计数。

②Pattern类与Matcher类

在java中,正则表达式主要依赖java.util.regex中的Pattern和Matcher类实现。

Pattern类:

用于表示编译后的正则表达式模式,它提供了静态方法来编译正则表达式,将其转换为模式对象。通过Pattern类编译后的模式对象可以被重复使用,避免了每次匹配都需要重新编译正则表达式的开销。

Matcher类:

用于执行匹配操作,它是由给定的输入字符串和Pattern对象进行匹配并且提供了丰富的方法来进行匹配操作,比如查找、替换、提取等。

Pattern类&Matcher类方法:
Pattern类调用方法(静态方法):

在这里插入图片描述

1、public static Pattern compile(String regex)

源码:

public static Pattern compile(String regex) {
	return new Pattern(regex, 0);
}

说明:

Pattern类的一个静态方法,用于将给定的正则表达式字符串编译为一个Pattern对象。这个方法通常用于将一个常见的正则表达式字符串编译成一个Pattern对象,以便后续的重复使用

示例:

Pattern pattern = Pattern.compile("a*b");
2、public static Pattern compile(String regex, int flags)

源码:

public static Pattern compile(String regex, int flags) {
    return new Pattern(regex, flags);
}

说明:

Pattern.compile(String regex, int flags)Pattern类的一个静态方法,用于根据给定的正则表达式字符串和标志位来编译成一个Pattern对象。这个方法允许你在编译正则表达式时指定一些标志,以控制匹配的行为。

参数regex是要编译的正则表达式字符串,flags是一个整数,表示匹配的标志位。常用的标志位包括:

  • Pattern.CASE_INSENSITIVE:忽略大小写进行匹配。
  • Pattern.MULTILINE:多行模式,即^$匹配每一行的开始和结束,而不是整个输入的开始和结束。
  • Pattern.DOTALL.可以匹配任意字符,包括换行符。
  • Pattern.UNICODE_CASE:启用Unicode感知的大小写折叠。
  • Pattern.UNIX_LINES:启用Unix换行模式,即只识别\n作为换行符。

使用这个重载的compile方法,可以更灵活地控制正则表达式的匹配行为。

示例:

//正则表达式"a*b"编译成一个Pattern对象,并指定了忽略大小写和多行模式的标志位。这样就可以在后续的匹配操作中,按照指定的标志位规则进行匹配
Pattern pattern = Pattern.compile("a*b", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
3、public static boolean matches(String regex, CharSequence input)

源码:

public static boolean matches(String regex, CharSequence input) {
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(input);
    return m.matches();
}

说明:

Pattern.matches(String regex, CharSequence input)Pattern 类的一个静态方法,用于判断给定的输入字符串是否完全匹配指定的正则表达式。

参数 regex 是要用来进行匹配的正则表达式字符串,参数 input 是要进行匹配的输入字符序列。

这个方法会尝试将整个输入序列与正则表达式进行匹配,如果整个输入字符串与正则表达式完全匹配,则返回 true;否则返回 false

示例:

boolean isMatch = Pattern.matches("a*b", "aaaab");
//运行结果: isMatch = true
//上面的代码将会用正则表达式 "ab" 对字符串 "aaaab" 进行匹配,因为 "aaaab" 符合 "a" 的模式,所以 isMatch 会被赋值为 true
4、public static String quote(String s)

源码:

 public static String quote(String s) {
        int slashEIndex = s.indexOf("\\E");
        if (slashEIndex == -1)
            return "\\Q" + s + "\\E";

        int lenHint = s.length();
        lenHint = (lenHint < Integer.MAX_VALUE - 8 - lenHint) ?
                (lenHint << 1) : (Integer.MAX_VALUE - 8);

        StringBuilder sb = new StringBuilder(lenHint);
        sb.append("\\Q");
        int current = 0;
        do {
            sb.append(s, current, slashEIndex)
                    .append("\\E\\\\E\\Q");
            current = slashEIndex + 2;
        } while ((slashEIndex = s.indexOf("\\E", current)) != -1);

        return sb.append(s, current, s.length())
                .append("\\E")
                .toString();
    }

说明:

Pattern.quote(String s)Pattern 类的一个静态方法,用于返回指定字符串的字面量模式字符串。这个方法可以将输入的字符串转换为字面量模式,以便在正则表达式中进行精确匹配。于正则表达式中可能包含特殊字符,如果需要在正则表达式中精确匹配一个字符串,就需要对字符串进行转义处理,这时可以使用 quote 方法来实现。

示例:

//我们希望匹配字符串 "(.)",但是这个字符串包含了正则表达式中的特殊字符 "()" 和 ".",为了确保在正则表达式中能够精确匹配这个字符串,我们可以使用 quote 方法来转义这个字符串,得到的 regex 就是 \(\.\*\),它可以在正则表达式中精确匹配原始的字符串 "(.*)"。
String input = "(.*)";
String regex = Pattern.quote(input);
Pattern实例对象调用方法:

在这里插入图片描述

1、创建Pattern实例方式

首先可以看Pattern内部的源码中的构造器,可以发现是私有的,因此我们不能通过new实例的方式去创建Pattern的实例

private Pattern(String p, int f)

我们可以通过调用Pattern的静态方法quotecompile来创建实例,具体的静态方法的调用已经在上面说明了。

2、public String pattern()

源码

public String pattern() {
    return pattern;
}

说明:

pattern() 方法是在 Pattern 类中的一个公共方法,它返回该正则表达式对象所表示的模式,你可以使用这个 Pattern 对象调用 pattern() 方法,以获取该正则表达式的字符串表示形式。

示例:

String regex = "ab+c";
Pattern pattern = Pattern.compile(regex);
String patternString = pattern.pattern();
System.out.println(patternString); // 输出:"ab+c"

3、public Matcher matcher(CharSequence input)

源码:

public Matcher matcher(CharSequence input) {
    if (!compiled) {
        synchronized(this) {
            if (!compiled)
                compile();
        }
    }
    Matcher m = new Matcher(this, input);
    return m;
}

说明:

matcher(CharSequence input) 方法是在 Pattern 类中的一个公共方法,它用于创建一个匹配器对象,并将指定的输入序列与正则表达式进行匹配。

在 Java 中,可以使用 Pattern 类的 matcher(CharSequence input) 方法来创建一个 Matcher 对象,该对象可以用于执行匹配操作。CharSequence 表示一个字符序列,可以是字符串或其他类型的字符序列。

示例:

我们首先定义了一个正则表达式字符串 \\d+,表示匹配一个或多个数字。然后,我们定义了一个输入字符串 input,其值为 "12345"

接下来,我们使用 Pattern.compile() 方法编译正则表达式,并将返回的 Pattern 对象赋值给 pattern 变量。然后,我们使用 pattern.matcher(input) 方法创建一个 Matcher 对象,该对象用于对输入序列进行匹配。

最后,我们调用 matcher.matches() 方法来检查输入序列是否完全匹配正则表达式。如果匹配成功,则返回 true,否则返回 false。在上述示例中,由于输入字符串 "12345" 完全匹配正则表达式 \\d+,所以输出结果为 true

因此,matcher(CharSequence input) 方法的作用是创建一个匹配器对象,并将指定的输入序列与正则表达式进行匹配。

String regex = "\\d+";
String input = "12345";

Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);

boolean isMatch = matcher.matches();
System.out.println(isMatch); // 输出:true

4、public String toString()

源码

public String toString() {
    return pattern;
}

说明:

可以看到其返回值和调用pattern()是一样的,在这里就不过多赘述。

5、public Predicate<String> asPredicate()

源码:

public Predicate<String> asPredicate() {
    return s -> matcher(s).find();
}

说明:

asPredicate() 方法是在 Pattern 类中的一个公共方法,它返回一个 Predicate<String> 对象,用于将正则表达式作为谓词进行匹配。

在 Java 中,Predicate 是一个函数接口,它接受一个输入参数并返回一个布尔值结果。Predicate<String> 表示该谓词接受一个字符串类型的输入参数。

示例:

我们首先定义了一个正则表达式字符串 \\d+,表示匹配一个或多个数字。然后,我们使用 Pattern.compile() 方法编译正则表达式,并将返回的 Pattern 对象赋给 pattern 变量。

接下来,我们调用 pattern.asPredicate() 方法,将正则表达式转换为一个 Predicate<String> 对象,并将其赋值给 predicate 变量。

最后,我们可以使用 predicate.test(String input) 方法来测试输入字符串是否与正则表达式匹配。如果匹配成功,则返回 true,否则返回 false。在上述示例中,由于输入字符串 "123" 符合正则表达式 \\d+ 的模式,所以第一次输出结果为 true;而输入字符串 "abc" 不符合该模式,所以第二次输出结果为 false

因此,asPredicate() 方法的作用是将正则表达式转换为一个 Predicate<String> 对象,用于对输入字符串进行匹配。

String regex = "\\d+";
Pattern pattern = Pattern.compile(regex);

Predicate<String> predicate = pattern.asPredicate();

System.out.println(predicate.test("123")); // 输出:true
System.out.println(predicate.test("abc")); // 输出:false

6、public int flags()

源码:

public int flags() {
    return flags0;
}

说明:

flags() 方法是在 Pattern 类中的一个公共方法,用于返回当前正则表达式模式的标志位(flags)。

在 Java 中,Pattern 类的正则表达式模式可以使用一些标志来修改其行为。这些标志可以通过在正则表达式字符串中添加特殊的标记来指定。

以下是一些常用的标志:

  • CASE_INSENSITIVE:忽略大小写匹配。
  • MULTILINE:启用多行模式,更改 ^$ 的行为。
  • DOTALL:启用 dotall 模式,使 . 可以匹配任何字符,包括换行符。
  • UNICODE_CASE:根据 Unicode 字符属性进行匹配和转换。
  • CANON_EQ:启用规范等价匹配。

flags() 方法将返回一个整数值,表示当前正则表达式模式的标志位。该整数值是由上述标志的按位或组合而成。

示例:

我们首先定义了一个正则表达式字符串 "abc",然后使用 Pattern.compile() 方法编译该正则表达式,并将 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE 作为第二个参数传递给方法,这样我们同时启用了 CASE_INSENSITIVEMULTILINE 两个标志。

接下来,我们调用 pattern.flags() 方法,返回一个整数值,表示当前正则表达式模式的标志位。

最后,我们打印出 flags 的值,它将输出 2,表示 CASE_INSENSITIVEMULTILINE 两个标志被启用。

因此,flags() 方法的作用是返回当前正则表达式模式的标志位的整数值。

String regex = "abc";
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

int flags = pattern.flags();

System.out.println(flags); // 输出:2

7、public String[] split(CharSequence input)

源码:

public String[] split(CharSequence input) {
    return split(input, 0);
}

说明:

split(CharSequence input) 方法是在 Pattern 类中的一个公共方法,用于将输入序列根据正则表达式进行拆分,并返回拆分后的字符串数组

在 Java 中,可以使用 Pattern 类的 split(CharSequence input) 方法来将一个字符序列按照正则表达式进行拆分。CharSequence 表示一个字符序列,可以是字符串或其他类型的字符序列。

示例:

我们首先定义了一个正则表达式字符串 \\s+,表示匹配一个或多个空格。然后,我们定义了一个输入字符串 input,其值为 "Hello World Java",包含多个连续空格。

接下来,我们使用 Pattern.compile() 方法编译正则表达式,并将返回的 Pattern 对象赋给 pattern 变量。然后,我们调用 pattern.split(input) 方法,将输入字符串按照正则表达式进行拆分。拆分后的结果将存储在一个字符串数组 parts 中。

最后,我们使用一个循环遍历输出 parts 数组中的每个元素,以显示拆分后的结果

String regex = "\\s+";
String input = "Hello   World   Java";

Pattern pattern = Pattern.compile(regex);
String[] parts = pattern.split(input);

for (String part : parts) {
    System.out.println(part);
}

/*
运行结果:
Hello
World
Java
*/
8、public String[] split(CharSequence input, int limit)

源码:

public String[] split(CharSequence input, int limit) {
    int index = 0;
    boolean matchLimited = limit > 0;
    ArrayList<String> matchList = new ArrayList<>();
    Matcher m = matcher(input);

    // Add segments before each match found
    while(m.find()) {
        if (!matchLimited || matchList.size() < limit - 1) {
            if (index == 0 && index == m.start() && m.start() == m.end()) {
                // no empty leading substring included for zero-width match
                // at the beginning of the input char sequence.
                continue;
            }
            String match = input.subSequence(index, m.start()).toString();
            matchList.add(match);
            index = m.end();
        } else if (matchList.size() == limit - 1) { // last one
            String match = input.subSequence(index,
                                             input.length()).toString();
            matchList.add(match);
            index = m.end();
        }
    }

    // If no match was found, return this
    if (index == 0)
        return new String[] {input.toString()};

    // Add remaining segment
    if (!matchLimited || matchList.size() < limit)
        matchList.add(input.subSequence(index, input.length()).toString());

    // Construct result
    int resultSize = matchList.size();
    if (limit == 0)
        while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
            resultSize--;
    String[] result = new String[resultSize];
    return matchList.subList(0, resultSize).toArray(result);
}

说明:

可以使用 Pattern 类的 split(CharSequence input, int limit) 方法来将一个字符序列按照正则表达式进行拆分,并限制拆分的数量。CharSequence 表示一个字符序列,可以是字符串或其他类型的字符序列,而 limit 参数表示拆分的最大数量

示例:

我们首先定义了一个正则表达式字符串 \\s+,表示匹配一个或多个空格。然后,我们定义了一个输入字符串 input,其值为 "Hello World Java",包含多个连续空格。

接下来,我们使用 Pattern.compile() 方法编译正则表达式,并将返回的 Pattern 对象赋给 pattern 变量。然后,我们调用 pattern.split(input, 2) 方法,将输入字符串按照正则表达式进行拆分,并限制拆分的最大数量为 2。拆分后的结果将存储在一个字符串数组 parts 中。

最后,我们使用一个循环遍历输出 parts 数组中的每个元素,以显示拆分后的结果。

String regex = "\\s+";
String input = "Hello   World   Java";

Pattern pattern = Pattern.compile(regex);
String[] parts = pattern.split(input, 2);

for (String part : parts) {
    System.out.println(part);
}

/*
运行结果:
Hello
World   Java

*/
9、public Stream<String> splitAsStream(final CharSequence input)

源码:

public Stream<String> splitAsStream(final CharSequence input) {
    class MatcherIterator implements Iterator<String> {
        private Matcher matcher;
        // The start position of the next sub-sequence of input
        // when current == input.length there are no more elements
        private int current;
        // null if the next element, if any, needs to obtained
        private String nextElement;
        // > 0 if there are N next empty elements
        private int emptyElementCount;

        public String next() {
            if (!hasNext())
                throw new NoSuchElementException();

            if (emptyElementCount == 0) {
                String n = nextElement;
                nextElement = null;
                return n;
            } else {
                emptyElementCount--;
                return "";
            }
        }

        public boolean hasNext() {
            if (matcher == null) {
                matcher = matcher(input);
                // If the input is an empty string then the result can only be a
                // stream of the input.  Induce that by setting the empty
                // element count to 1
                emptyElementCount = input.length() == 0 ? 1 : 0;
            }
            if (nextElement != null || emptyElementCount > 0)
                return true;

            if (current == input.length())
                return false;

            // Consume the next matching element
            // Count sequence of matching empty elements
            while (matcher.find()) {
                nextElement = input.subSequence(current, matcher.start()).toString();
                current = matcher.end();
                if (!nextElement.isEmpty()) {
                    return true;
                } else if (current > 0) { // no empty leading substring for zero-width
                    // match at the beginning of the input
                    emptyElementCount++;
                }
            }

            // Consume last matching element
            nextElement = input.subSequence(current, input.length()).toString();
            current = input.length();
            if (!nextElement.isEmpty()) {
                return true;
            } else {
                // Ignore a terminal sequence of matching empty elements
                emptyElementCount = 0;
                nextElement = null;
                return false;
            }
        }
    }
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
        new MatcherIterator(), Spliterator.ORDERED | Spliterator.NONNULL), false);
}

说明:

splitAsStream(final CharSequence input) 方法是在 Pattern 类中的一个公共方法,用于将输入序列根据正则表达式进行拆分,并返回一个 Stream<String> 流,在流中包含了拆分后的字符串元素。

可以使用 Pattern 类的 splitAsStream(final CharSequence input) 方法来将一个字符序列按照正则表达式进行拆分,并生成一个流对象,该流中包含了拆分后的字符串元素。

示例:

我们首先定义了一个正则表达式字符串 \\s+,表示匹配一个或多个空格。然后,我们定义了一个输入字符串 input,其值为 "Hello World Java",包含多个连续空格。

接下来,我们使用 Pattern.compile() 方法编译正则表达式,并将返回的 Pattern 对象赋给 pattern 变量。然后,我们调用 pattern.splitAsStream(input) 方法,将输入字符串按照正则表达式进行拆分,并生成一个 Stream<String> 流对象,其中包含了拆分后的字符串元素。

最后,我们使用 forEach() 方法遍历流中的每个字符串元素,并打印输出。

import java.util.regex.Pattern;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        String regex = "\\s+";
        String input = "Hello   World   Java";

        Pattern pattern = Pattern.compile(regex);
        Stream<String> stream = pattern.splitAsStream(input);

        stream.forEach(System.out::println);
    }
}
/*
运行结果:
Hello
World
Java

*/

Matcher类调用方法(静态方法):
1、public static String quoteReplacement(String s)

源码:

public static String quoteReplacement(String s) {
    if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1))
        return s;
    StringBuilder sb = new StringBuilder();
    for (int i=0; i<s.length(); i++) {
        char c = s.charAt(i);
        if (c == '\\' || c == '$') {
            sb.append('\\');
        }
        sb.append(c);
    }
    return sb.toString();
}

说明:

quoteReplacement(String s) 方法是在 Matcher 类中的一个静态方法,用于将输入字符串转义,以便在替换操作中使用。

在 Java 中,正则表达式的替换操作通常使用 Matcher 类的 replaceAll(String replacement)replaceFirst(String replacement) 方法。当替换字符串中包含一些特殊字符(如 $\ 等)时,为了正确处理这些字符,需要对替换字符串进行转义。

quoteReplacement(String s) 方法接受一个字符串参数 s,并返回一个转义后的字符串,该字符串可以安全地用作替换操作的替换字符串。

代码判断输入字符串 s 中是否包含 \$ 字符,即 (s.indexOf('\\') == -1) && (s.indexOf('$') == -1)。如果不包含任何特殊字符,则直接返回原始字符串 s

如果输入字符串中包含了 \$ 字符,则进入循环处理。代码使用一个 StringBuilder 对象 sb 来构建转义后的字符串。通过遍历输入字符串的每个字符,将特殊字符 \$ 进行转义处理,并添加到 sb 中。

具体地,当遇到特殊字符时,代码使用 sb.append('\\'); 将一个反斜杠字符添加到 sb 中,以进行转义。然后,将当前字符 c 添加到 sb 中。

最后,循环结束后,代码通过 sb.toString() 方法将 StringBuilder 转换为字符串,并返回转义后的结果。

示例:

public class RegTest {
    public static void main(String[] args) {
        String input = "Hello $ World";

        String replacement = Matcher.quoteReplacement("$1");

        String result = input.replaceAll("\\$", replacement);

        System.out.println(replacement);    //输出:\$1
        System.out.println(result); // 输出:Hello $1 World

    }
}

/*
运行结果:
\$1
Hello $1 World
*/
Matcher实例对象调用方法:
1、Matcher创建实例对象

Matcher也没有自己默认的构造器,因此,需要通过patter实例对象的pattern.matcher(CharSequence input)方法,来创建一个Matcher对象

示例

 String regex = "\\d+";
String input = "12345";

Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
2、public boolean find()

源码

public boolean find() {
    int nextSearchIndex = last;
    if (nextSearchIndex == first)
        nextSearchIndex++;

    // If next search starts before region, start it at region
    if (nextSearchIndex < from)
        nextSearchIndex = from;

    // If next search starts beyond region then it fails
    if (nextSearchIndex > to) {
        for (int i = 0; i < groups.length; i++)
            groups[i] = -1;
        return false;
    }
    return search(nextSearchIndex);
}

说明:

find() 方法是在 Matcher 类中的一个公共方法,用于在输入字符串中查找与正则表达式模式匹配的下一个子序列

在 Java 中,Matcher 对象表示了对某个输入字符串进行正则表达式匹配的状态。find() 方法通过在输入字符串中寻找与模式匹配的下一个子序列,来进行匹配操作。

该方法返回一个布尔值,如果在输入字符串中找到了匹配的子序列,则返回 true,否则返回 false

示例:

我们使用之前提到的方式创建了一个 Matcher 对象,并调用 find() 方法进行匹配操作。

如果匹配成功(即在输入字符串中找到了匹配的子序列),则通过 matcher.group() 方法获取匹配的结果,并打印输出。否则,输出未找到匹配。

执行上述代码,将输出以下内容:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String regex = "\\d+";
        String input = "12345";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        if (matcher.find()) {
            System.out.println("Match found: " + matcher.group());
        } else {
            System.out.println("No match found.");
        }
    }
}

/*
运行结果:
Match found: 12345
*/

3、public boolean find(int start)

源码:

public boolean find(int start) {
    int limit = getTextLength();
    if ((start < 0) || (start > limit))
        throw new IndexOutOfBoundsException("Illegal start index");
    reset();
    return search(start);
}

说明:

find(int start) 方法是在 Matcher 类中的一个公共方法,用于在输入字符串中从指定位置开始查找与正则表达式模式匹配的下一个子序列。

该方法接受一个整数参数 start,表示开始查找的位置索引。它会从指定位置开始在输入字符串中查找与正则表达式模式匹配的下一个子序列。

find(int start) 方法返回一个布尔值,如果在指定位置之后的输入字符串中找到了匹配的子序列,则返回 true,否则返回 false

示例:

我们使用之前提到的方式创建了一个 Matcher 对象,并定义了一个开始查找的位置索引 start

然后,我们调用 find(int start) 方法并传入 start 参数来执行匹配操作。如果在指定位置之后的输入字符串中找到了匹配的子序列,则通过 matcher.group() 方法获取匹配的结果,并打印输出。否则,输出未找到匹配。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String regex = "\\d+";
        String input = "12345";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        int start = 2; // 从索引 2 开始查找

        if (matcher.find(start)) {
            System.out.println("Match found: " + matcher.group());
        } else {
            System.out.println("No match found.");
        }
    }
}

/*
运行结果:
Match found: 345

*/

4、public String group()

源码:

public String group() {
    return group(0);
}

说明:

group() 方法是在 Matcher 类中的一个公共方法,用于返回与最后一次匹配操作相匹配的字符串。

在执行匹配操作后,如果 find() 方法返回 true,则表示找到了匹配的子序列。此时,可以使用 group() 方法获取最后一次匹配操作所匹配的字符串。

group() 方法返回一个字符串,即最后一次匹配操作所匹配的子序列。

示例:

public class RegTest {
    public static void main(String[] args) {
        String regex = "\\d";
        String input = "12345";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        while(matcher.find()){
            System.out.println("Match found: " + matcher.group());
        }
    }
}

/*
运行结果:
Match found: 1
Match found: 2
Match found: 3
Match found: 4
Match found: 5

*/
5、public String group(int group)

源码:

public String group(int group) {
    if (first < 0)
        throw new IllegalStateException("No match found");
    if (group < 0 || group > groupCount())
        throw new IndexOutOfBoundsException("No group " + group);
    if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
        return null;
    return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
}

说明:

group(int group) 方法是在 Matcher 类中的一个公共方法,用于返回与最后一次匹配操作中指定组号相匹配的字符串。

在正则表达式中,使用圆括号 () 可以创建捕获组(Capture Group)。当进行匹配操作时,每个捕获组都有一个对应的组号,从 1 开始递增。group(int group) 方法接受一个整数参数 group,表示要获取的捕获组的组号。

group(int group) 方法返回一个字符串,即最后一次匹配操作中指定组号所匹配的子序列。

示例:

我们使用之前提到的方式创建了一个 Matcher 对象,并调用 find() 方法进行匹配操作。

如果匹配成功(即在输入字符串中找到了匹配的子序列),则通过 matcher.group(int group) 方法获取指定组号的匹配结果,并打印输出。这里分别获取了第一个捕获组和第二个捕获组的结果。不指定捕获组名称,默认捕获组从1开始递增编号

group(int group) 方法的作用是返回与最后一次匹配操作中指定组号相匹配的字符串。它可以用于获取指定组号的匹配结果并进行后续处理。注意,组号必须大于等于 1,且不能超过实际捕获组的数量,否则会抛出 IndexOutOfBoundsException 异常

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String regex = "(\\d+)-(\\w+)";
        String input = "12345-abcd";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        if (matcher.find()) {
            System.out.println("First group: " + matcher.group(1));
            System.out.println("Second group: " + matcher.group(2));
        } else {
            System.out.println("No match found.");
        }
    }
}

/*
运行结果:
First group: 12345
Second group: abcd
*/

6、public String group(String name)

源码:

public String group(String name) {
    int group = getMatchedGroupIndex(name);
    if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
        return null;
    return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
}

说明:

group(String name) 方法是在 Matcher 类中的一个公共方法,用于返回与最后一次匹配操作中指定命名组名相匹配的字符串。

在正则表达式中,可以使用命名捕获组(Named Capture Group)来标识和引用特定的子表达式。每个命名捕获组都有一个唯一的名称,可以通过该名称来引用对应的匹配结果。

group(String name) 方法接受一个字符串参数 name,表示要获取的命名捕获组的名称。

group(String name) 方法返回一个字符串,即最后一次匹配操作中指定命名组名所匹配的子序列。

示例:

我们使用之前提到的方式创建了一个 Matcher 对象,并调用 find() 方法进行匹配操作。

如果匹配成功(即在输入字符串中找到了匹配的子序列),则通过 matcher.group(String name) 方法获取指定命名组名的匹配结果,并打印输出。这里分别获取了名为 “number” 的命名捕获组和名为 “word” 的命名捕获组的结果。

group(String name) 方法的作用是返回与最后一次匹配操作中指定命名组名相匹配的字符串。它可以用于获取指定命名组名的匹配结果并进行后续处理。如果没有找到指定的命名组名,或者命名组名不合法,会抛出 IllegalArgumentException 异常

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String regex = "(?<number>\\d+)-(?<word>\\w+)";
        String input = "12345-abcd";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        if (matcher.find()) {
            System.out.println("Number group: " + matcher.group("number"));
            System.out.println("Word group: " + matcher.group("word"));
        } else {
            System.out.println("No match found.");
        }
    }
}

/*
运行结果:
Number group: 12345
Word group: abcd

*/
7、public boolean matches()

源码:

public boolean matches() {
    return match(from, ENDANCHOR);
}

说明:

matches() 方法是在 Matcher 类中的一个公共方法,用于尝试将整个输入序列与正则表达式进行匹配。

该方法会尝试将整个输入序列与正则表达式进行匹配,而不仅仅是寻找匹配的子序列。只有当整个输入序列完全匹配正则表达式时,matches() 方法才返回 true,否则返回 false

示例:

因为下面的正则表达式无法完全匹配输入的12345,所以matches返回的false

public class RegTest {
    public static void main(String[] args) {


        String regex = "\\d\\d\\d";
        String input = "12345";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        if (matcher.matches()) {
            System.out.println("Input matches the regular expression.");
        } else {
            System.out.println("Input does not match the regular expression.");
        }
    }
}
/*
运行结果:
Input does not match the regular expression.

*/
8、public Pattern pattern()

源码:

public Pattern pattern() {
    return parentPattern;
}

说明:

pattern() 方法是在 Matcher 类中的一个公共方法,用于返回与当前 Matcher 对象关联的正则表达式模式。

正则表达式模式通过 Pattern 类的实例来表示。pattern() 方法返回的就是与当前 Matcher 对象关联的 Pattern 实例。

示例:

我们首先创建了一个 Pattern 对象,用于表示正则表达式模式。然后,我们将该模式与输入字符串进行匹配操作,得到对应的 Matcher 对象。

接下来,我们调用 pattern() 方法获取与当前 Matcher 对象关联的正则表达式模式,并将其打印输出。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String regex = "\\d+";
        String input = "12345";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        Pattern associatedPattern = matcher.pattern();
        System.out.println("Associated pattern: " + associatedPattern.pattern());
    }
}
/*
运行结果:
Associated pattern: \d+
*/

9、public String replaceAll(String replacement)

源码:

public String replaceAll(String replacement) {
    reset();
    boolean result = find();
    if (result) {
        StringBuilder sb = new StringBuilder();
        do {
            appendReplacement(sb, replacement);
            result = find();
        } while (result);
        appendTail(sb);
        return sb.toString();
    }
    return text.toString();
}

说明:

replaceAll(String replacement) 方法是在 Matcher 类中的一个公共方法,用于将匹配到的子序列替换为指定的字符串。

该方法会查找输入字符串中与正则表达式模式匹配的所有子序列,并将其替换为指定的字符串 replacement

replaceAll(String replacement) 方法接受一个字符串参数 replacement,表示要替换匹配子序列的字符串。

replaceAll() 方法返回一个新的字符串,其中所有匹配的子序列都被替换为指定的字符串。

示例:

们使用之前提到的方式创建了一个 Matcher 对象,并调用 replaceAll(String replacement) 方法进行替换操作。

该示例中,正则表达式模式 \d+ 可以匹配连续的数字。我们将输入字符串中所有匹配到的数字替换为字符 “X”。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String regex = "\\d+";
        String input = "Hello 123 World 456";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        String replacedString = matcher.replaceAll("X");
        System.out.println("Replaced string: " + replacedString);
    }
}
/*
输出内容:
Replaced string: Hello X World X

*/

10、public String replaceAll(Function<MatchResult, String> replacer) (java9/java1.9)

源码:

public String replaceAll(Function<MatchResult, String> replacer) {
    Objects.requireNonNull(replacer);
    reset();
    boolean result = find();
    if (result) {
        StringBuilder sb = new StringBuilder();
        do {
            int ec = modCount;
            String replacement =  replacer.apply(this);
            if (ec != modCount)
                throw new ConcurrentModificationException();
            appendReplacement(sb, replacement);
            result = find();
        } while (result);
        appendTail(sb);
        return sb.toString();
    }
    return text.toString();
}

说明:

String replaceAll(Function<MatchResult, String> replacer) 方法是在 Matcher 类中提供的一个功能,用于基于指定的模式替换字符串的部分内容。

它接受一个 函数式接口Function 参数 replacer,该参数用于确定每个匹配子串的替换值。replacer 函数接受一个 MatchResult 对象,表示当前的匹配结果,并返回替换后的字符串。

示例:

import java.util.function.Function;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MatcherReplaceAllExample {
    public static void main(String[] args) {
        String text = "Hello, world! How are you?";
        
        // Define a regular expression pattern
        Pattern pattern = Pattern.compile("\\b\\w{3}\\b");
        
        // Create a matcher from the input text
        Matcher matcher = pattern.matcher(text);
        
        // Use replaceAll with a lambda expression as the replacer
        //这里表示在调用函数式接口的方法的时候,将每次匹配的内容以大写的形式返回
        String result = matcher.replaceAll(match -> match.group().toUpperCase());
        
        System.out.println(result);
    }
}
/*
运行结果:
HELLO, WORLD! HOW ARE YOU?
*/
11、public int start()

源码:

public int start() {
    if (first < 0)
        throw new IllegalStateException("No match available");
    return first;
}

说明:

返回上次匹配到内容的初始索引,如果上次匹配没有内容,抛出异常

示例:

 String text = "Hello, world! How are you?";

        // Define a regular expression pattern
        Pattern pattern = Pattern.compile("\\b\\w{3}\\b");

        // Create a matcher from the input text
        Matcher matcher = pattern.matcher(text);

        while(matcher.find()){
            System.out.println("当前匹配内容:" + matcher.group() +",当前匹配的索引是:" + matcher.start());
        }
    }
}

/*
运行结果:
当前匹配内容:How,当前匹配的索引是:14
当前匹配内容:are,当前匹配的索引是:18
当前匹配内容:you,当前匹配的索引是:22

*/
12、public int start(int group)

源码:

public int start(int group) {
    if (first < 0)
        throw new IllegalStateException("No match available");
    if (group < 0 || group > groupCount())
        throw new IndexOutOfBoundsException("No group " + group);
    return groups[group * 2];
}

说明:

public String group(int group)类似,上一次匹配结果,捕获组次序为group的的索引值

13、public int start(String name)

源码:

public int start(String name) {
    return groups[getMatchedGroupIndex(name) * 2];
}

说明:

public String group(String Name)类似,上一次匹配结果,捕获组名称为name的的索引值

14、public String toString()

源码:

public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("java.util.regex.Matcher")
        .append("[pattern=").append(pattern())
        .append(" region=")
        .append(regionStart()).append(',').append(regionEnd())
        .append(" lastmatch=");
    if ((first >= 0) && (group() != null)) {
        sb.append(group());
    }
    sb.append(']');
    return sb.toString();
}

说明:

Matcher类的toString()方法返回一个包含Matcher对象的字符串表示形式的字符串。

根据我的知识截至日期,即2023年3月1日,Matcher类在Java中确实具有public String toString()方法。该方法可用于将Matcher对象转换为代表对象状态的字符串。

示例:

public static void main(String[] args) {


        String text = "Hello, world! How are you?";

        // Define a regular expression pattern
        Pattern pattern = Pattern.compile("\\b\\w{3}\\b");

        // Create a matcher from the input text
        Matcher matcher = pattern.matcher(text);

        while(matcher.find()){
            System.out.println(matcher.toString());
        }
}

/*
运行结果:
java.util.regex.Matcher[pattern=\b\w{3}\b region=0,26 lastmatch=How]
java.util.regex.Matcher[pattern=\b\w{3}\b region=0,26 lastmatch=are]
java.util.regex.Matcher[pattern=\b\w{3}\b region=0,26 lastmatch=you]

包含了pattern正则表达式模式、region:匹配的区间范围、lastmatch:上一次匹配结果

*/
15、public int end()

源码:

public int end() {
    if (first < 0)
        throw new IllegalStateException("No match available");
    return last;
}

说明:

返回上一次匹配结果的结束索引位置,如果上次没有匹配,那么报错

示例:

public class RegTest {
    public static void main(String[] args) {


        String text = "Hello, world! How are you?";

        // Define a regular expression pattern
        Pattern pattern = Pattern.compile("\\b\\w{3}\\b");

        // Create a matcher from the input text
        Matcher matcher = pattern.matcher(text);

        while(matcher.find()){
            System.out.println(matcher.end());
        }
    }
}    
16、public int end(int group)

说明:

public String group(int group)类似,不做过多解释

17、public int end(String name)

说明:

public String group(String name)类似,不做过多解释

18、public int groupCount()

源码:

public int groupCount() {
    return parentPattern.capturingGroupCount - 1;
}

说明:

Matcher类的groupCount()方法是用于获取匹配器中捕获组的数量

示例:

我们使用正则表达式模式"(Hello) (World)“来创建一个Matcher对象。然后,我们使用groupCount()方法获取匹配器中的捕获组数量,并将结果打印出来。在这个例子中,正则表达式包含两个捕获组,因此输出是"Number of capturing groups: 2”。

String input = "Hello World";
Pattern pattern = Pattern.compile("(Hello) (World)");
Matcher matcher = pattern.matcher(input);

int count = matcher.groupCount();
System.out.println("Number of capturing groups: " + count);
/*
运行结果:
Number of capturing groups: 2

*/

19、public int groupCount(int group)

说明:和public String group(int group)类似,不做过多解释

20、public int groupCount(String name)

说明:和public String group(String name)类似,不做过多解释

21、public boolean lookingAt()

源码:

public boolean lookingAt() {
    return match(from, NOANCHOR);
}

说明:

lookingAt()Matcher类中的一个方法,用于检查输入字符串的起始部分是否与正则表达式模式匹配。

示例:

String input = "Hello World";
Pattern pattern = Pattern.compile("Hello");
Matcher matcher = pattern.matcher(input);

boolean isLookingAt = matcher.lookingAt();
System.out.println("Looking at: " + isLookingAt);

/*
运行结果:
Looking at: true
*/

如果将input改为String input = "123Hello World";,则会报错失败。

22、public Matcher region(int start, int end)

源码:

public Matcher region(int start, int end) {
    if ((start < 0) || (start > getTextLength()))
        throw new IndexOutOfBoundsException("start");
    if ((end < 0) || (end > getTextLength()))
        throw new IndexOutOfBoundsException("end");
    if (start > end)
        throw new IndexOutOfBoundsException("start > end");
    reset();
    from = start;
    to = end;
    return this;
}

说明:

Matcher类的region()方法用于设置匹配器的区域范围,即指定在输入字符串中进行匹配操作的起始位置和结束位置。返回值为Matcher对象本身,因此可以进行链式调用。

参数说明:

  • start:指定匹配操作的起始位置(包括)。

  • end:指定匹配操作的结束位置(不包括)。

示例:

String input = "Hello World";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input).region(6, 11);
System.out.println("Matches: " + matcher.toString());

/*
运行结果:
Matches: java.util.regex.Matcher[pattern=World region=6,11 lastmatch=]

*/
23、public int regionEnd()

源码:

public int regionEnd() {
    return to;
}

说明:

regionEnd()Matcher类中的一个方法,用于返回匹配器当前设置的区域范围的结束位置(不包括)

示例:

String input = "Hello World";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);

matcher.region(6, 11);

int regionEnd = matcher.regionEnd();
System.out.println("Region end: " + regionEnd);

/*
运行结果:
Region end: 11
*/
24、public int regionStart()

源码:

public int regionStart() {
    return from;
}

说明:

regionStart()Matcher 类中的一个方法,用于返回匹配器当前设置的区域范围的起始位置。

示例:

String input = "Hello World";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);

matcher.region(6, 11);

int regionStart = matcher.regionStart();
System.out.println("Region start: " + regionStart);

/*
运行结果:
Region start: 6
*/
25、public String replaceFirst(String replacement)

源码:

public String replaceFirst(String replacement) {
    if (replacement == null)
        throw new NullPointerException("replacement");
    reset();
    if (!find())
        return text.toString();
    StringBuilder sb = new StringBuilder();
    appendReplacement(sb, replacement);
    appendTail(sb);
    return sb.toString();
}

说明:

replaceFirst(String replacement)Matcher 类中的一个方法,用于将匹配到的第一个子字符串替换为指定的替换字符串。

示例:

 String input = "Hello World World World!";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);

String replacedString = matcher.replaceFirst("Universe");
System.out.println("Replaced string: " + replacedString);

/*
运行结果:
Replaced string: Hello Universe World World!
*/
26、 public String replaceFirst(Function<MatchResult, String> replacer)

源码:

 public String replaceFirst(Function<MatchResult, String> replacer) {
        Objects.requireNonNull(replacer);
        reset();
        if (!find())
            return text.toString();
        StringBuilder sb = new StringBuilder();
        int ec = modCount;
        String replacement = replacer.apply(this);
        if (ec != modCount)
            throw new ConcurrentModificationException();
        appendReplacement(sb, replacement);
        appendTail(sb);
        return sb.toString();
    }

说明:

类似于上面的public String replaceAll(Function<MatchResult, String> replacer)

示例:

String input = "Hello World World World!";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);

String replacedString = matcher.replaceFirst(match -> match.group().toUpperCase());
System.out.println("Replaced string: " + replacedString);

/*
运行结果:
Replaced string: Hello WORLD World World!

*/

27、public Matcher reset()

源码:

public Matcher reset() {
    first = -1;
    last = 0;
    oldLast = -1;
    for(int i=0; i<groups.length; i++)
        groups[i] = -1;
    for(int i=0; i<locals.length; i++)
        locals[i] = -1;
    for (int i = 0; i < localsPos.length; i++) {
        if (localsPos[i] != null)
            localsPos[i].clear();
    }
    lastAppendPosition = 0;
    from = 0;
    to = getTextLength();
    modCount++;
    return this;
}

说明:

reset()Matcher 类中的一个方法,用于重置匹配器的状态,将其重新设置为初始状态。

示例:

我们首先使用正则表达式模式"World"创建一个 Matcher 对象,并将其应用于输入字符串"Hello World"。然后,我们使用 find() 方法进行一次匹配操作,并打印出第一个匹配到的子字符串 “World”。接下来,我们使用 reset() 方法重置匹配器的状态,将其恢复到初始状态。再次使用 find() 方法进行匹配操作,可以看到匹配器又重新从输入字符串中找到了与正则表达式匹配的子字符串 “World”。

String input = "Hello World";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);

matcher.find();
System.out.println("First match: " + matcher.group());

matcher.reset();

matcher.find();
System.out.println("Reset match: " + matcher.group());

/*
运行结果:
First match: World
Reset match: World

*/
28、public Matcher reset(CharSequence input)

源码:

public Matcher reset(CharSequence input) {
    text = input;
    return reset();
}

说明:

reset(CharSequence input)Matcher 类中的一个方法,用于重置匹配器的状态,并将新的输入字符序列应用于匹配器

示例:

String input = "Hello World";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);

matcher.find();
System.out.println("First match: " + matcher.group());

CharSequence newInput = "Hello Universe";
matcher.reset(newInput);

matcher.find();
System.out.println("Reset match: " + matcher.group());

/*
运行结果:
First match: World
Reset match: Universe

*/

29、public MatchResult toMatchResult()

源码:

public MatchResult toMatchResult() {
    return toMatchResult(text.toString());
}

说明:

toMatchResult()Matcher 类中的一个方法,用于返回当前匹配操作的结果作为 MatchResult 对象。

示例:

我们首先使用正则表达式模式"World"创建一个 Matcher 对象,并将其应用于输入字符串"Hello World"。然后,我们使用 find() 方法进行一次匹配操作。接下来,我们使用 toMatchResult() 方法获取当前匹配操作的结果作为 MatchResult 对象。通过 MatchResult 对象,我们可以访问匹配到的子字符串、起始位置和结束位置等信息,并将其打印出来。

请注意,toMatchResult() 方法返回的是一个 MatchResult 对象,其中包含了有关匹配结果的各种信息。通过 MatchResult 对象,您可以获取匹配到的子字符串以及它在输入字符串中的起始位置和结束位置等相关信息。

String input = "Hello World";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);

matcher.find();
MatchResult matchResult = matcher.toMatchResult();

System.out.println("Matched substring: " + matchResult.group());
System.out.println("Start index: " + matchResult.start());
System.out.println("End index: " + matchResult.end());

/*
输出:
Matched substring: World
Start index: 6
End index: 11

*/

30、 public Matcher usePattern(Pattern newPattern)

源码:

public Matcher usePattern(Pattern newPattern) {
    if (newPattern == null)
        throw new IllegalArgumentException("Pattern cannot be null");
    parentPattern = newPattern;

    // Reallocate state storage
    int parentGroupCount = Math.max(newPattern.capturingGroupCount, 10);
    groups = new int[parentGroupCount * 2];
    locals = new int[newPattern.localCount];
    for (int i = 0; i < groups.length; i++)
        groups[i] = -1;
    for (int i = 0; i < locals.length; i++)
        locals[i] = -1;
    localsPos = new IntHashSet[parentPattern.localTCNCount];
    modCount++;
    return this;
}

说明:

usePattern(Pattern newPattern)Matcher 类中的一个方法,用于将匹配器切换到一个新的正则表达式模式

该方法的函数签名如下:

public Matcher usePattern(Pattern newPattern)

参数 newPattern 表示要切换到的新的正则表达式模式。

返回值为 Matcher 对象本身,因此可以进行链式调用

示例:

我们首先使用正则表达式模式 “World” 创建一个 Matcher 对象,并将其应用于输入字符串 “Hello World”。然后,我们使用 find() 方法进行一次匹配操作,并打印出第一个匹配到的子字符串 “World”。接下来,我们创建了另一个正则表达式模式 “Hello” 并使用 usePattern() 方法将匹配器切换到这个新的模式。再次使用 find() 方法进行匹配操作,可以看到匹配器从新的模式中找到了与之匹配的子字符串 “Hello”。

请注意,usePattern(Pattern newPattern) 方法用于切换 Matcher 对象的正则表达式模式。通过使用不同的模式,您可以重复使用同一个 Matcher 对象进行多个不同模式的匹配操作。调用此方法后,匹配器的状态将被重置,并从新的模式开始进行匹配操作。

String input = "Hello World";
Pattern pattern1 = Pattern.compile("World");
Matcher matcher = pattern1.matcher(input);

matcher.find();
System.out.println("First match: " + matcher.group());

Pattern pattern2 = Pattern.compile("Hello");
matcher.usePattern(pattern2);

matcher.find();
System.out.println("New pattern match: " + matcher.group());

/*
运行结果:
First match: World
New pattern match: Hello


*/

二、正则表达式语法

①常用的元字符

元字符: 有特定含义的字符,都只匹配对应规则的一个字符,常见的元字符如下

常用元字符语法:

代码说明
.匹配除换行符以外的任意字符
\w匹配字母或数字或下划线或汉字
\s匹配任意的空白符
\d匹配数字
\b匹配单词的开始或结束
\f匹配换页符
\n匹配换行符
^匹配字符串的开始(在集合字符里^a表示非(不匹配)的意思
$匹配字符串的结束

详细分析/案例:

1、.

匹配对象

1 a_*+
-/#

正则表达式

.

匹配结果

共找到 9 处匹配:
1
 
a
_
*
+
-
/
#

2、\w

匹配对象

1a_

正则表达式

\w

匹配结果

共找到 3 处匹配:
1
a
_

3、\s

匹配对象

1 a_*+
-/#

正则表达式

\s

匹配结果

共找到 2 处匹配:
1和a中间的空格
+后面的换行

4、\d

匹配对象

\d

正则表达式

123

匹配结果

共找到 3 处匹配:
1
2
3

5、\b

匹配对象

o oi oie oier

正则表达式

\boie\b

匹配结果

共找到 1 处匹配:
oie

6、^

匹配对象

o oi oie oier

正则表达式1

^o 

匹配结果1

共找到 1 处匹配:
o 

正则表达式2

^o      //后面有一个空格

匹配结果2

共找到 1 处匹配:
o 

正则表达式3

^oi

匹配结果3

没有匹配

通过^来检验输入的字符串是否符合身份证号码或手机号码:

^\d{15}$:匹配15位均为数字的身份证号

^\d{11}$:匹配11位手机号码

7、$

匹配对象

o oi oie oier

正则表达式1

r$

匹配结果1

共找到 1 处匹配:
r

正则表达式2

er$

匹配结果2

共找到 1 处匹配:
er

正则表达式3

qr$

匹配结果3

(没有匹配)
②反义字符

反义字符:多用于查找除某个字符以外其他任意字符均可以的情况(把元字符以大写形式表示)

常用反义字符语法:

代码/语法说明
\W匹配任意不是字母,数字,下划线,汉字的字符
\S匹配任意不是空白符的字符
\D匹配任意非数字的字符
\B匹配不是单词开头或结束的位置
[^x]匹配除了x以外的任意字符
[^aeiou]匹配除了aeiou这几个字母以外的任意字符

详细分析/案例:

1、\W

匹配对象

1 a_*+
-/#

正则表达式

\w

匹配结果

共找到 3 处匹配:
1
a
_

2、\S

匹配对象

1 a_*+
-/#

正则表达式

\S

匹配结果

共找到 8 处匹配:
1
a
_
*
+
-
/
#

3、\D

匹配对象

1 a_*+-/#

正则表达式

\D

匹配结果

共找到 8 处匹配:
 
a
_
*
+
-
/
#

4、\B

匹配对象

o oi oie oier ie

正则表达式

\Bie\B

匹配结果

共找到 1 处匹配:
ie

5、[^x]

匹配对象

xer

正则表达式

[^x]

匹配结果

共找到 2 处匹配:
e
r

6、[^aeiou]

匹配对象

xer

正则表达式

[^aeiou]

匹配结果

共找到 2 处匹配:
x
r
③限定字符

限定字符:多用于重复匹配次数

常用限定字符语法:

代码/语法说明
*重复零次或更多次
+重复一次或更多次
?重复零次或一次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次

详细分析/案例:

1、*

匹配对象

123

正则表达式

\d* //匹配重复0次或多次的数字

匹配结果

共找到 2 处匹配(除了12345还有一个结果是空,因此这里找到了2处匹配):
12345

2、+

匹配对象

12345

正则表达式

\d+

匹配结果

共找到 1 处匹配:
12345

3、?

匹配对象

12345

正则表达式

\d?

匹配结果

共找到 6 处匹配:
1
2
3
4
5

4、{n}

匹配对象

12345

正则表达式

\d{2}

匹配结果

共找到 2 处匹配:
12
34

5、{n,}

匹配对象

12345

正则表达式

\d{2,}		//匹配重复至少4次的数字

匹配结果

共找到 1 处匹配:
12345

6、{n,m}

匹配对象

12345

正则表达式

\d{2,3}

匹配结果

共找到 2 处匹配:
123
45
④转义字符

转义字符:在实际的开发中,可能会遇到要比配元字符的情况,这个时候就需要进行字符转义,如元字符 .*\ 需要转换为\. \* \\

详细分析/案例:

匹配对象:

.*\

正则表达式

\.\*\\

匹配结果

共找到 1 处匹配:
.*\

多用于满足不同情况的选择,用“|”将不同的条件分割开来,比如有些固定电话区号有三位,有些有四位,这个时候可以采用字符分枝

详细分析/案例:

匹配对象

123-12345678
1234-12345678
12-123445678
123-123

正则表达式

\d{3}-\d{8}|\d{4}-\d{8}

匹配结果

共找到 2 处匹配:
123-12345678
1234-12345678
⑤字符分组

字符分组: 多用于将多个字符重复,主要通过使用小括号()来进行分组

如:(\d\w){3} 重复匹配3次(\d\w)

详细分析/案例:

匹配对象

123.123.123.123

正则表达式

((25[0-5]|2[0-4][0-9]|[0-1]\d\d)\.){3}(25[0-5]|2[0-4][0-9]|[0-1]\d\d)		//匹配ip地址通用

匹配结果

共找到 1 处匹配:
123.123.123.123

分析:

先把IP地址分为两部分一部分是123.123.123. 另一部分是123,又因Ip最大值为255,所以先使用分组,然后在组里边再进行选择,组里也有三部分,0-199,200-249,250-255,分别和上述的表达是对应,最后还要注意分组之后还要加上一个.,因为是元字符所以要转义故加上. 然后再把这部分整体看做是一个组,重复三次,再加上仅有数字的一组也就是不带.的那一组即可完成IP地址的校验

常用分组语法:

捕获:

代码/语法说明
(exp)匹配exp,并捕获文本到自动命名的组里
(?exp)匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name’exp)
(?:exp)匹配exp,不捕获匹配的文本,也不给此分组分配组号

1、(exp)

这个表达式(exp)表示一个捕获组,其中exp代表要匹配的内容。在正则表达式中,捕获组用于将匹配到的子字符串提取出来,以便后续处理或引用。当使用这样的捕获组进行匹配时,匹配到的内容将会被捕获并保存起来,以便后续可以通过索引编号来引用。例如,在一些编程语言的正则表达式匹配中,可以通过\1\2等来引用第一个、第二个捕获组中匹配到的内容。

2、(?<name>exp)

这个表达式使用了?<name>来定义命名捕获组,它表示一个命名捕获组,其中name是捕获组的名称,exp则是要匹配的内容。在一些正则表达式引擎中,这种语法被用来支持命名捕获组,允许通过名称来引用捕获到的内容,而不是依赖于索引编号。例如:(?\w+) 表示将 \w+ 匹配的内容命名为 “word”

3、(?:exp)

非捕获型的捕获组,它表示一个非捕获型的子表达式,其中exp代表要匹配的内容。在正则表达式中,非捕获型的捕获组允许对子表达式进行分组但不会捕获匹配的内容,这意味着匹配结果不会被保存起来供后续引用。

零宽断言:

零宽断言是正则表达式中一种高级的匹配技术,它用于指定一个位置,这个位置满足一定的条件。零宽断言本身不匹配任何字符,它只是对当前位置的内容进行判断,从而在匹配过程中起到限定条件的作用。在正则表达式中,常见的零宽断言包括正向前瞻、负向前瞻、正向后顾和负向后顾。

代码/语法说明
(?=exp)匹配exp前面的位置
(?<=exp)匹配exp后面的位置
(?!exp)匹配后面跟的不是exp的位置
(?<!exp)匹配前面不是exp的位置
  1. 正向前瞻(Positive Lookahead):
    • 正向前瞻用于匹配满足某种条件之后的位置,语法为 A(?=B),表示匹配紧跟在 A 之后的位置,该位置之后的字符序列必须匹配 B。
    • 例如,Windows(?=95|98|NT|2000) 可以匹配 “Windows” 后面跟着 “95”、“98”、“NT” 或 “2000” 的位置。
  2. 负向前瞻(Negative Lookahead):
    • 负向前瞻用于匹配不满足某种条件之后的位置,语法为 A(?!B),表示匹配紧跟在 A 之后的位置,该位置之后的字符序列不能匹配 B。
    • 例如,Windows(?!95|98|NT|2000) 可以匹配 “Windows” 后面不跟着 “95”、“98”、“NT” 或 “2000” 的位置。
  3. 正向后顾(Positive Lookbehind):
    • 正向后顾用于匹配满足某种条件之前的位置,语法为 (?<=B)A,表示匹配紧挨着的 A 之前的位置,该位置之前的字符序列必须匹配 B。
    • 例如,(?<=95|98|NT|2000)Windows 可以匹配 “Windows” 前面紧挨着 “95”、“98”、“NT” 或 “2000” 的位置。
  4. 负向后顾(Negative Lookbehind):
    • 负向后顾用于匹配不满足某种条件之前的位置,语法为 (?<!B)A,表示匹配紧挨着的 A 之前的位置,该位置之前的字符序列不能匹配 B。
    • 例如,(?<!95|98|NT|2000)Windows 可以匹配 “Windows” 前面不紧挨着 “95”、“98”、“NT” 或 “2000” 的位置。

注释:

代码/语法说明
(?#comment)这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读
⑥懒惰匹配和贪婪匹配

贪婪匹配:正则表达式中包含重复的限定符时,通常的行为是匹配尽可能多的字符。

懒惰匹配:有时候需要匹配尽可能少的字符。

例如: a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。但是我们此时可能需要匹配的是ab这样的话就需要用到懒惰匹配了。懒惰匹配会匹配尽可能少的字符

常用的懒惰匹配限定符

代码/语法说明
*?重复任意次,但尽可能少重复
+?重复1次或更多次,但尽可能少重复
??重复0次或1次,但尽可能少重复
{n,m}?重复n到m次,但尽可能少重复
{n,}?重复n次以上,但尽可能少重复
⑦后向引用

后向引用用于重复搜索前面某个分组匹配的文本。

使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推

示例:\b(\w+)\b\s+\1\b可以用来匹配重复的单词,像go go, 或者kitty kitty。

这个表达式首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字(\b(\w+)\b),这个单词会被捕获到编号为1的分组中,然后是1个或几个空白符(\s+),最后是分组1中捕获的内容(也就是前面匹配的那个单词)(\1)。

你也可以自己指定子表达式的组名。要指定一个子表达式的组名,请使用这样的语法:(?\w+)(或者把尖括号换成’也行:(?‘Word’\w+)),这样就把\w+的组名指定为Word了。要反向引用这个分组捕获的内容,你可以使用\k,所以上一个例子也可以写成这样:\b(?\w+)\b\s+\k\b

⑧零宽断言

有时候需要查找某些匹配之前或之后的东西,这个时候就需要用到们像\b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言

(?=exp)也叫零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp。比如\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找I’m singing while you’re dancing.时,它会匹配sing和danc。

(?<=exp)也叫零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式exp。比如(?<=\bre)\w+\b会匹配以re开头的单词的后半部分(除了re以外的部分),例如在查找reading a book时,它匹配ading。

⑨正则表达式语法相关整理(来自菜鸟)
一、校验数字的表达式
数字:^[0-9]*$
n位的数字:^\d{n}$
至少n位的数字:^\d{n,}$
m-n位的数字:^\d{m,n}$
零和非零开头的数字:^(0|[1-9][0-9]*)$
非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(\.[0-9]{1,2})?$
带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})$
正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
有两位小数的正实数:^[0-9]+(\.[0-9]{2})?$
有1~3位小数的正实数:^[0-9]+(\.[0-9]{1,3})?$
非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
非负整数:^\d+$ 或 ^[1-9]\d*|0$
非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

二、校验字符的表达式
汉字:^[\u4e00-\u9fa5]{0,}$
英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
长度为3-20的所有字符:^.{3,20}$
由26个英文字母组成的字符串:^[A-Za-z]+$
由26个大写英文字母组成的字符串:^[A-Z]+$
由26个小写英文字母组成的字符串:^[a-z]+$
由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+
禁止输入含有~的字符:[^~]+

三、特殊需求表达式
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?
InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
手机号码:^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$
电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
电话号码正则表达式(支持手机号码,3-4位区号,7-8位直播号码,1-4位分机号): ((\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$)
身份证号(15位、18位数字),最后一位是校验位,可能为数字或字符X:(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)
帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在 8-10 之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,10}$
强密码(必须包含大小写字母和数字的组合,可以使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
日期格式:^\d{4}-\d{1,2}-\d{1,2}
一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
钱的输入格式:
有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$
这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧。下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$
这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$
这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里
xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
中文字符的正则表达式:[\u4e00-\u9fa5]
双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
空白行的正则表达式:\n\s*\r (可以用来删除空白行)
HTML标记的正则表达式:<(\S*?)[^>]*>.*?|<.*? /> ( 首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
IPv4地址:((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}

三、附后续补充内容:

1、平衡组、递归匹配、负向零宽断言等知识有空了继续整理

2、matcher的 appendReplacement()、appendTail()、hasAnchoringBounds()、hasTransparentBounds()、public boolean hitEnd()、useAnchoringBounds()、useTransparentBounds()、requireEnd()

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值