【Java正则表达式】深度介绍,讲解+举例

元字符 (Metacharacter) - 转义符 \

  • 符号说明:在我们使用正则表达式去检索某些特殊字符的时候,需要使用到 转义符,否则检索不到结果,甚至会报错。
  • 注意:Java 中的正则表达式中,两个 \ 代表其他语言中的一个 \
  • 常见的需要用到转义符的字符有:.*+()$/?[]^{}

元字符 - 字符匹配符

  • [] :可接收的字符列表,例:[efgh],e、f、g、h 中的任意 1 个字符
  • [^] : 不接收的字符列表,例:[^abc], 除 a、b、c 之外的任意1个字符,包括数字和特殊符号
  • - :连字符,例:A-Z, 任意单个大写字母
  • . : 匹配除 \n 以外的任何字符,例:a…b,以 a 开头,b 结尾,中间包括2个任意字符的长度为4个字符串,如:aaab, a#*b
  • \d: 匹配单个数字字符,相当于[0-9], 例:\d{3}(\d)?, 包含3个或4个数字的字符串, 如:123、9876
  • \D: 匹配单个非数字字符,相当于[^0-9], 例:\D(\d)*, 以单个非数字字符开头,后接任意个数字字符串,如:a、A342
  • \w: 匹配单个数字,大小写字母字符,相当于[0-9a-zA-Z], 例:\d{3}\w{4}, 以3个数字字符开头的长度为7的数字字母字符串,如:234abcd、12345Pe
  • \W: 匹配单个非数字,非大小写字母字符,相当于[^0-9a-zA-Z], 例:\W+\d{2}, 以至少1个非数字字母字符开头,2个数字字符结尾的字符串。如:#29、#?@10

应用实例:
1、[a-z] : 表示可以匹配 a-z 中任意一个字符,比如 [a-z] 、[A-Z] 去匹配 a11c8,前者得到 a、c 两个结果,后者什么都没有。

2、Java 正则表达式默认是区分字母大小写的,如何实现不区分大小写:

  • (?!)abc 表示abc 都不区分大小写
  • a(?!)bc 表示 bc 不区分
  • a((?!)b)c 表示只有 b 不区分大小写
  • Pattern pat = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE)

3、[^a-z] 表示可以匹配不是 a-z 中的任意一个字符,比如:用 [^a-z] 去匹配 “a11c8” 会得到 1、1、8 三个结果。
[^a-z]{2} 表示匹配连续2个不是 a-z 中的字符。

4、[abcd] 表示可以匹配 abcd 中的任意一个字符。

5、[^abcd] 表示可以匹配不是 abcd 中的任意一个字符。

6、\d 表示可以匹配 0-9 的任意一个数字,等价于 [0-9]。

7、\D 表示可以匹配不是 0-9 中的任意一个数字,等价于 [^0-9]

8、\w 表示匹配任意一个英文字符、数字、下划线,等价于 [a-zA-Z0-9_]

9、\W 与 \w 相反,匹配任意一个不是 英文字符、数字、下划线 的字符,等价于 [^a-zA-Z0-9_]

10、\s 匹配任何一个空白字符 (空格、制表符、换行符等)

11、\S 匹配任何一个非空白字符,和 \s 相反

12、. (点)匹配出一个 \n 以外的所有字符,如需要匹配本身,则使用 .

元字符 – 选择匹配符

在匹配某个字符串的时候是选择性的,即:既可以匹配这个,又可以匹配那个,这时你需要使用到选择匹配符 |

符号含义示例
|匹配 | 之前或之后的表达式ab | cd
public class RegExpTest4 {

    public static void main(String[] args) {

        Pattern pattern = Pattern.compile("ab|AB");
        Matcher matcher = pattern.matcher("abcdefgABCDEFG");

        while (matcher.find()){
            System.out.println(matcher.group(0));
        }
    }
}
输出:
ab
AB

元字符 – 限定符

用于指定其前面的字符或组合项连续出现多少次

符号含义示例说明举例
*指定字符重复 0 次或 n 次 (0到多)(abc)*仅包含任意个 abc 的字符串abc、abcabcDabc
+指定字符重复1次或n 次 (至少1次,1到多)m+(abc)*以至少1个m 开头,后接任意个 abc 的字符串m、mabc、mabcabc
?指定字符重复 0 次或 1 次(最多一次,0 到 1)m+abc?以至少1个m 开头,后接ab 或 abc 的字符串mab、mabc、mmmab、mmabc
{n}只能匹配 n 个字符[abcd]{3}由 abcd 中任意一个字母组成的长度为3个字符串abc、dbc、adc
{n,}指定至少 n 个匹配 >=n[abcd]{3,}由abcd 中任意一个字母组成的长度不小于3个字符串aab、dbc、aaabdc
{n,m}指定至少 n 个但不多于 m 个匹配 (>=n && <=m)[abcd]{3,5}由 abcd 中任意一个字母组成的长度不小于3且不大于5的字符串abc、abcd、aaaaa、bcdab
public static void main(String[] args) {

    String content = "1111111aaa_hello_welcome_ _#@!";
    String regStr = "a{3}";//表示匹配 3 个 a,等价于 aaa

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println(matcher.group(0));
    }
}
输出:
aaa
public static void main(String[] args) {

    String content = "1111111aaa_hello_welcome_ _#@!";
    String regStr = "1{3}";//表示匹配 111

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println(matcher.group(0));
    }
}
输出:
111
111
public static void main(String[] args) {

    String content = "1111111aaa_23467hello_welcome_ _#@!";
    String regStr = "\\d{2}";//表示匹配 两位的任意数字

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println(matcher.group(0));
    }
}
输出:
11
11
11
23
46
public static void main(String[] args) {

    String content = "1111111aaaaaaa_23467hello_welcome_ _#@!";
    String regStr = "a{3,4}";//表示匹配 aaa 或者 aaaaa

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println(matcher.group(0));
    }
}
输出:
aaaa
aaa

注意:Java 正则表达式默认是 “贪婪模式”, 即尽可能匹配多的字符。 所以上述例子先输出4个a 再输出 3个 a。

public static void main(String[] args) {

    String content = "12345678aaaaaaa_23467hello_welcome_ _#@!";
    String regStr = "\\d{3,5}";//表示匹配 3位数 4位数 5位数

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println(matcher.group(0));
    }
}
输出:
12345
678
23467

注意:Java 正则表达式默认是 “贪婪模式”, 即尽可能匹配多的字符。

public static void main(String[] args) {

    String content = "12345678aaaaaaa_23467hello_welcome_ _#@!";
    String regStr = "\\d+";//表示匹配 1个或多个数字

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println(matcher.group(0));
    }
}
输出:
12345678
23467
public static void main(String[] args) {

    String content = "12345678aaa_23467he_!2";
    String regStr = "\\d*";//表示匹配 0个或多个数字

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println(matcher.group(0));
    }
}
输出:
12345678




23467




2


Process finished with exit code 0

注:由于 * 是匹配0个到多个,所以非数字字符也会输出,只不过是空字符串,最后数字2后面多出1行是因为字符串在内存中是以 \0 结尾,\0 在ASCII码表中代表 空字符。

public static void main(String[] args) {

    String content = "a12345678aaa_23467he_!2";
    String regStr = "a1?";//表示匹配 0个或多个数字

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println(matcher.group(0));
    }
}
输出:
a1
a
a
a

元字符 – 定位符

符号含义示例说明举例
^指定起始字符^[0-9]+[a-z]*以至少1个数字开头,后接任意个小写字母的字符串123、6aa、555edf
$指定结束字符^[0-9]-[a-z]+$以1个数字开头后接连字符 - ,并以至少1个小写字母结尾的字符串1-a、123-abc
\b匹配目标字符串的边界han\b这里说的字符串的边界指的是子串间有空格,或是目标字符串的结束位置hanmeimeisphan nnhan
\B匹配目标字符串的非边界han\\B和 \\b 的含义相反hanmeimeisphan nnhan
public static void main(String[] args) {

    String content = "12345678aaa_23467he_!2";
    String regStr = "^[0-9]+[a-z]*";//以至少1个数字开头,后接任意个小写字母的字符串

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println(matcher.group(0));
    }
}
输出:
12345678aaa

注:如果是文本以字母开头,则匹配不到

public static void main(String[] args) {

    String content = "1234-abb";
    String regStr = "^[0-9]+-[a-z]+";//以至少1个数字开头,中间用-连接,末尾是至少1个小写字母的字符串

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println(matcher.group(0));
    }
}
输出:
1234-abb

分组 – 捕获分组

常用分组构造形式 说明

  • (pattern)

非命名捕获。 捕获匹配的子字符串。编号为零的第一个捕获(group(0))是由整个正则表达式模式匹配的文本,其他捕获结果则根据左括号的顺序从1开始自动编号(group(1), group(2)…)。

  • (?<name>pattern)

命名捕获。 将匹配的子字符串捕获到一个组名称或编号名称中。用于 name 的字符串不能包含任何标点符号,并且不能以数字开头。可以使用单引号替代尖括号,例如:(?’name’)

1、分组: 我们可以用圆括号组成一个比较复杂的匹配模式,那么一个圆括号的部分我们可以看作是一个子表达式/一个分组。
2、捕获: 把正则表达式中子表达式/分组匹配的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用,从左向右,以分组的左括号为标志,第一个出现的分组的组号 是1,第二个为2,以此类推。组0代表的是整个正则式。
3、反向引用: 圆括号的内容被捕获后,可以在这个括号后被使用,从而写出一个比较实用的匹配模式,这个我们称之为反向引用,这种引用既可以是在正则表达式内部,也可以是在正则表达式外部,内部反向引用方式:\分组号,外部反向引用方式:$分组号

public static void main(String[] args) {

    String content = "hanshuping 1122hanhan4455ipo";
    String regStr = "(\\d\\d)(\\d\\d)";//匹配4个数字的字符串,并将匹配到的子字符串分成2组

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println("find=" + matcher.group(0));
        System.out.println("group(1)=" + matcher.group(1));
        System.out.println("group(2)=" + matcher.group(2));
    }
}
输出:
find=1122
group(1)=11
group(2)=22
find=4455
group(1)=44
group(2)=55
public static void main(String[] args) {

    String content = "hanshuping 1122hanhan4455ipo";
    String regStr = "(?<z1>\\d\\d)(?<z2>\\d\\d)";//匹配4个数字的字符串,并将匹配到的子字符串分成2组, 并分别给2个组命名为 z1 和 z2

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println("find=" + matcher.group(0));
        System.out.println("group(1)=" + matcher.group(1));
        System.out.println("group(z1)=" + matcher.group("z1"));
        System.out.println("group(2)=" + matcher.group(2));
        System.out.println("group(z2)=" + matcher.group("z2"));
    }
}
输出:
find=1122
group(1)=11
group(z1)=11
group(2)=22
group(z2)=22
find=4455
group(1)=44
group(z1)=44
group(2)=55
group(z2)=55

分组 – 非捕获分组

常用分组构造形式 说明

  • (?:pattern)

匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用 “or” 字符(|) 组合模式部件的情况很有用。例如:”industr(?:y|ies)” 是比 “industry|industries” 更经济的表达式。

  • (?=pattern)

它是一个非捕获匹配。例如:”Windows (?=95|98|NT|2000)” 匹配 “Windows 2000” 中的 “Windows”,但不匹配 “Windows 3.1” 中的 “Windows”。

  • (?!pattern)

该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配。例如:”Windows (?!95|98|NT|2000)” 匹配 “Windows 3.1” 中的 “Windows”,但不匹配 “Windows 2000” 中的 “Windows”。

public static void main(String[] args) {

    String content = "hello 韩梅梅同学, welcome 韩梅梅老师,Thanks 韩梅梅女士";
    String regStr = "韩梅梅(?:同学|老师|女士)";//等价于 "韩梅梅同学|韩梅梅老师|韩梅梅女士"

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println("find=" + matcher.group(0));
    }
}
输出:
find=韩梅梅同学
find=韩梅梅老师
find=韩梅梅女士

注意:这里不能使用 group(1),因为 (?:pattern) 不能看成是分组形式,虽然它看起来像个分组。

public static void main(String[] args) {

    String content = "hello 韩梅梅同学, welcome 韩梅梅老师,Thanks 韩梅梅女士";
    String regStr = "韩梅梅(?=同学|老师)";//查找后面带 "同学","老师" 的韩梅梅子串

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println("find=" + matcher.group(0) + ", index=" + matcher.start());
    }
}
输出:
find=韩梅梅, index=6
find=韩梅梅, index=21

注意:这里不能使用 group(1),因为 (?=pattern) 不能看成是分组形式。

public static void main(String[] args) {

    String content = "hello 韩梅梅同学, welcome 韩梅梅老师,Thanks 韩梅梅女士";
    String regStr = "韩梅梅(?!同学|老师)";//查找后面不带 "同学","老师" 的韩梅梅子串,可以把 ! 看成是 非门取反

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println("find=" + matcher.group(0) + ", index=" + matcher.start());
    }
}
输出:
find=韩梅梅, index=34

注意:这里不能使用 group(1),因为 (?!pattern) 不能看成是分组形式。

分组 – 反向引用

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

1、 要匹配2个连续相同的数字:(\d)\1
2、 要匹配5个连续相同的数字:(\d)\1{4}
3、 要匹配个位与千位相同,十位与百位相同的数 5225 1551:(\d)(\d)\2\1

public static void main(String[] args) {
    String content = "1234hanmeimei1990199112213333Thankyou~!";
    String regStr = "(\\d)(\\d)\\2\\1";


    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println("find=" + matcher.group(0) + ", index=" + matcher.start());
    }
}
输出:
find=1991, index=17
find=1221, index=21
find=3333, index=25

4、 请在字符串中检索商品编号,形式如:12321-333999111 这样的号码,要求满足前面是一个五位数,然后一个 – 号,然后一个九位数,连续的每三位要相同

public static void main(String[] args) {
    String content = "1234hanmeimei12321-3339991111990199112213333Thankyou~!";
    String regStr = "\\d{5}-(\\d)\\1{2}(\\d)\\2{2}(\\d)\\3{2}";


    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println("find=" + matcher.group(0) + ", index=" + matcher.start());
    }
}
输出:
find=12321-333999111, index=13

5、 口吃语句矫正:

public static void main(String[] args) {
    String content = "我...我要...学学学学学学编程Java!";

    /**
     * 1、去掉 ...
     * 2、去掉重复字
     */
    Pattern pattern = Pattern.compile("\\.");
    Matcher matcher = pattern.matcher(content);

    content = matcher.replaceAll("");
    System.out.println(content);

    pattern = Pattern.compile("(.)\\1+");//内部反向引用
    matcher = pattern.matcher(content);

    content = matcher.replaceAll("$1");//外部反向引用
    System.out.println(content);

    /**
     * 用一行代码实现
     */
    content = Pattern.compile("(.)\\1+").matcher(content).replaceAll("$1");
    System.out.println(content);
}
输出:
我我要学学学学学学编程Java!
我要学编程Java!
我要学编程Java

贪婪模式 与 非贪婪模式

  • 贪婪模式:
public static void main(String[] args) {

    String content = "hanmeimei 1122hanhan4455ipo";
    String regStr = "\\d+?";//\\d+ 代表匹配 1 到 多 个数字字符串,贪婪模式下会匹配尽可能长的子串,非贪婪模式下只匹配长度为1的子串

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println("find=" + matcher.group(0) + ", index=" + matcher.start());
    }
}
输出:
find=1, index=10
find=1, index=11
find=2, index=12
find=2, index=13
find=4, index=20
find=4, index=21
find=5, index=22
find=5, index=23
  • 非贪婪模式
public static void main(String[] args) {

    String content = "hanmeimei 1122hanhan4455ipo";
    String regStr = "\\d+";//\\d+ 代表匹配 1 到 多 个数字字符串,贪婪模式下会匹配尽可能长的子串,非贪婪模式下只匹配长度为1的子串

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println("find=" + matcher.group(0) + ", index=" + matcher.start());
    }
}
输出:
find=1122, index=10
find=4455, index=20

正则表达式三个常用类

java.util.regex 包主要包括以下三个类 Pattern类、Matcher类、PatternSyntaxException

  • Pattern 类

pattern 对象是一个正则表达式对象。Pattern 类没有公共构造函数。要创建 Pattern 对象,需要调用其公共静态函数,返回一个 Pattern对象。该函数接受一个正则表达式作为它的第一个参数,如:
Pattern pattern = Pattern.compile(regStr);

  • Matcher 类

Matcher 对象是对输入字符串进行解释和匹配的引擎。与Pattern 类一样,Matcher也没有公共构造函数。需要调用 Pattern 对象的 matcher 函数来获得一个 Matcher对象。

  • PatternSyntaxException

PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。

  • Matcher类

方法 说明
public int start() 返回值是总体匹配的初始索引
public int start(int group) 返回值是总体匹配中,由给定组捕获的子序列的初始索引
public int end() 返回值是总体匹配的最后一个字符的偏移值,从0开始
public int end(int group) 返回值是总体匹配中,由给定组捕获的子序列的最后一个字符的偏移值,从0开始
public boolean lookingAt() 尝试将从区域开头开始的输入序列与该模式匹配。
public boolean find() 尝试查找与该模式匹配的输入序列的下一个子序列。
public boolean find(int start) 重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
public boolean matches() 尝试将整个区域与模式匹配。
public Matcher appendRepalcement(StringBuffer sb, String replacement) 实现非终端添加和替换步骤
public StringBuffer appendTail(StringBuffer sb) 实现终端添加和替换步骤
public String replaceAll(String replacement) 替换模式与给定替换字符串相匹配的输入序列的每个子序列。
public String replaceFirst(String replacement) 替换模式与给定替换字符串匹配的输入序列的第一个子序列。
public static String quoteReplacement(String s) 返回指定字符串的字面替换字符串。这个方法返回一个字符串,就像传递给Matcher类的 appendReplacement 方法一个字面字符串一样工作。
public Matcher appendReplacement(StringBuffer sb, String replacement) 实现非终端添加和替换步骤。

public static void main(String[] args) {

    String content = "你好,韩梅梅女士,Hello 韩梅梅同学,Thanks 韩梅梅老师。";
    String regStr = "韩梅梅";

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    while (matcher.find()){
        System.out.println("find=" + matcher.group(0) + ", index=" + matcher.start());
    }

    //注意:返回的字符串是替换后的字符串,原字符串不会被替换
    String newContent = matcher.replaceAll("小明");
    System.out.println(newContent);
}
输出:
find=韩梅梅, index=3
find=韩梅梅, index=15
find=韩梅梅, index=28
你好,小明女士,Hello 小明同学,Thanks 小明老师。
  • String 类中的替换、分割和匹配
public static void main(String[] args) {
    String content = "13813945886";

    if(content.matches("1(38|39)\\d{8}")){
        System.out.println("匹配");
    } else {
        System.out.println("不匹配");
    }

}
public static void main(String[] args) {
    //要求按照 # 或 - 或 ~ 或 数字 来分割
    String content = "hello#abc-jack12smith~北京";

    String[] arr = content.split("#|-|~|\\d+");

    for (String s: arr){
        System.out.println(s);
    }
}
输出:
hello
abc
jack
smith
北京
public static void main(String[] args) {
    //替换一串文本中的 JDK 1.2 和 JDK 1.3 为 JDK1.8
    String content = "1999年4月27日,HotSpot虚拟机发布。HotSpot虚拟机发布时是作为" +
            "JDK 1.2的附加程序提供的,后来它成为了JDK 1.3及之后所有版本的" +
            "Sun JDK的默认虚拟机";

    content = content.replaceAll("JDK (1\\.2|1\\.3)", "JDK 1.8");

    System.out.println(content);
}
输出:
1999427日,HotSpot虚拟机发布。HotSpot虚拟机发布时是作为JDK 1.8的附加程序提供的,后来它成为了JDK 1.8及之后所有版本的Sun JDK的默认虚拟机
public static void main(String[] args) {
    /**
     * 电子邮件地址匹配
     * 只能有一个 @
     * @ 前面是用户名,可以是 a-z A-Z 0-9 _ -
     * @ 后面是域名,并且域名只能是英文字母,比如 sohu.com 或 tsinghua.org.cn
     *
     * 写出对应的正则表达式,验证输入的字符串是否满足规则
     */
    String content = "jizhidan112@qq.com.cn";
    String regStr = "[\\w-]+@([a-zA-Z]+\\.)+([a-zA-Z]+)";

    if(content.matches(regStr)){
        System.out.println("匹配");
    } else {
        System.out.println("不匹配");
    }

}

注意:. 在中括号[] 内表示 . 本身,如果在小括号 () 内则代表匹配符,需要进行转义 .

练习题

1、判断一串文本中是否都是汉字:

public static void main(String[] args) {

    String content = "韩梅梅女士";
    String regStr = "^[\u0391-\uffe5]+$";

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    if(matcher.find()){
        System.out.println("找到了");
    } else {
        System.out.println("未找到");
    }
}
输出:
找到了

2、验证邮政编码
要求:是1-9开头的6位数,比如123890

public static void main(String[] args) {

    String content = "123890";
    String regStr = "^[1-9]\\d{5}";

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    if(matcher.find()){
        System.out.println("找到了");
    } else {
        System.out.println("未找到");
    }
}

3、验证QQ号码
要求:是1-9开头的 5-10 位数,比如:12389、127200998

public static void main(String[] args) {

    String content = "127200998";
    String regStr = "^[1-9]\\d{4,9}";

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    if(matcher.find()){
        System.out.println("找到了");
    } else {
        System.out.println("未找到");
    }
}

4、验证手机号码
要求:必须是以13、14、15、18 开头的11位数,比如:13390982345

public static void main(String[] args) {

    String content = "13390982345";
    String regStr = "^1[3|4|5|8]\\d{9}$";

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    if(matcher.find()){
        System.out.println("找到了");
    } else {
        System.out.println("未找到");
    }
}

5、验证Url地址

public static void main(String[] args) {

    /**
     * 思路:
     * 1、先确定 url 的开始部分 http:// 或 https://, 使用 http(?:s?)://
     * 2、然后通过 ([\w-]+\.)+[\w-]+ 匹配 search.bilibili.com
     * 3、域名后面的接口匹配:(/[\w-.]*)*
     *    代表后面的接口名称以 / 开头,后接文本可以是 0-9 a-z A-Z . - 中的任意组合,并且 /xx 可以有多个
     * 4、接口后面的参数匹配:(^?[\w.?\-+=%&#]*)?
     *    代表以 ? 开头,后接文本可以是 0-9 a-z A-Z . - + = % & # 中的任意组合, 并且这样的组合有 0 - 1 个
     */
    String content = "https://search.bilibili.com/all/4r?keyword=%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F&from_source=webtop_search&spm_id_from=333.1007&search_source=3";
    String regStr = "^(http(s?)://)([\\w-]+\\.)+[\\w-]+(/[\\w-.]*)*(^?[\\w.?\\-+=%&#]*)?$";

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    /**
     * find 函数指的是在一串文本中,只要找到满足该正则表达式的子串即返回 true
     */
    if(matcher.find()){
        System.out.println("找到了");
    } else {
        System.out.println("未找到");
    }

    /**
     * matches 函数代表必须整体匹配,对上述例子来说,可以不在正则表达式的两边加 ^ 和 $ 限定符。
     */
    if(Pattern.matches(regStr, content)){
        System.out.println("找到了");
    } else {
        System.out.println("未找到");
    }
}

注意:
1、当 ? . * 等限定符在 [] 内时,此时匹配的是字符本身。
2、当限定符前面也是限定符时,如 \w- 、^?,此时后面的限定符就是字符本身。
3、[] 内,如果 – 连字符前面是限定符,如[\w-],则 - 代表符号本身,如果 – 前面是个字符,那么 – 代表连字符。如 [\wa-z]

Java源码中:matches() 函数实际上是替我们写了准备工作的部分代码:

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

6、验证是整数还是小数

public static void main(String[] args) {
    /**
     * 要求验证是不是整数或者小数
     * 提示:这个题要考虑正数和负数
     * 比如:123 -345 34.89 -87.9 -0.01 0.45 等
     */

    String content = "+1.89";
    String regStr = "[-+]?([1-9]\\d*|0)(\\.\\d+)?";

    if(content.matches(regStr)){
        System.out.println("匹配");
    } else {
        System.out.println("不匹配");
    }
}

思路:
1、 不能是034.56,所以应该以1-9开头,或者整数位就是0
2、 负数前面有 - ,正数前面可能有 +
3、 小数中间肯定有 . ,不是小数则没有 .

注意: | 选择匹配符,匹配的是 | 前面的整体 和后面的整体,在括号内是从左括号开始算起,不是前面1个字符开始算起。

public static void main(String[] args) {
    String content = "http://www.sohu.com:8080/abc/index.html";

    String regStr = "^([a-zA-Z]+)://([a-zA-Z.]+):(\\d+)[/\\w]*/([\\w.#@!]+)$";

    Pattern pattern = Pattern.compile(regStr);
    Matcher matcher = pattern.matcher(content);

    if(matcher.matches()){
        System.out.println("整体匹配=" + matcher.group(0));
        System.out.println("协议:" + matcher.group(1));
        System.out.println("域名:" + matcher.group(2));
        System.out.println("端口:" + matcher.group(3));
        System.out.println("文件:" + matcher.group(4));
    } else {
        System.out.println("不匹配");
    }
}
输出:
整体匹配=http://www.sohu.com:8080/abc/index.html
协议:http
域名:www.sohu.com
端口:8080
文件:index.html

注意:此表达式是根据需求编写,只是为了读取Url中的各个参数,实际开发中需根据需求调整。

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值