恭喜你,Get到一份 正则表达式 食用指南

先赞后看,养成习惯

前言

正则表达式

正则表达式: 定义一个搜索模式的字符串。java

正则表达式能够用于搜索、编辑和操做文本。面试

正则对文本的分析或修改过程为:首先正则表达式应用的是文本字符串(text/string),它会以定义的模式从左到右匹配文本,每一个源字符只匹配一次。正则表达式

Java中正则表达式的使用

字符串内置正则

在 Java 中有四个内置的运行正则表达式的方法,分别是 matches()split())replaceFirst()replaceAll()。注意 replace() 方法不支持正则表达式。segmentfault

方法 描述
s.matches("regex") 当仅且当正则匹配整个字符串时返回 true
s.split("regex") 按匹配的正则表达式切片字符串
s.replaceFirst("regex", "replacement") 替换首次匹配的字符串片断
s.replaceAll("regex", "replacement") 替换全部匹配的字符

示例代码学习

System.out.println("lby".matches("lby"));
            System.out.println("----------");

            String[] array = "l b y".split("\\s");
            for (String item : array) {
                System.out.println(item);
            }
            System.out.println("----------");

            System.out.println("l b y".replaceFirst("\\s", "-"));
            System.out.println("----------");

            System.out.println("l b y".replaceAll("\\s", "-"));

运行结果测试

true
----------
l
b
y
----------
l-b y
----------
l-b-y

regex包

java.util.regex 包主要包括如下三个类:url

  1. Pattern 类spa

    pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要建立一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式做为它的第一个参数。
  2. Matcher 类3d

    Matcher 对象是对输入字符串进行解释和匹配操做的引擎。与Pattern 类同样,Matcher 也没有公共构造方法。你须要调用 Pattern 对象的 matcher 方法来得到一个 Matcher 对象。
  3. PatternSyntaxExceptioncode

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

Java 中regex 包使用正则表达式基本步骤

  1. 经过正则表达式建立模式对象 Pattern。
  2. 经过模式对象 Pattern,根据指定字符串建立匹配对象 Matcher。
  3. 经过匹配对象 Matcher,根据正则表达式操做字符串。

例如

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

public class TestRegex {
    public static void main(String[] args) {
        //定义一个字符串
        String text = "Hello Regex!";
        //建立一个Pattern对象  能够认为根据正则表达式获取一个对应的对象
        Pattern pattern = Pattern.compile("\\w+");
        // Java 中忽略大小写,有两种写法:
        // Pattern pattern = Pattern.compile("\\w+", Pattern.CASE_INSENSITIVE);
        // Pattern pattern = Pattern.compile("(?i)\\w+"); // 推荐写法
        Matcher matcher = pattern.matcher(text);
        // 遍例全部匹配的序列
        while (matcher.find()) {
            System.out.print("Start index: " + matcher.start());
            System.out.print(" End index: " + matcher.end() + " ");
            System.out.println(matcher.group());
        }
        
    }
}

运行的结果为:

Start index: 0 End index: 5 Hello

Start index: 6 End index: 11 Regex、

以上代码看不懂没有关系,提早感觉一下正则的神奇,接下来咱们学习一下正则表达式的的语法。

正则表达式的语法

常见匹配符号

正则表达式 描述
. 匹配全部单个字符,除了换行符(Linux 中换行是 \n,Windows 中换行是 \r\n
^regex 正则必须匹配字符串开头
regex$ 正则必须匹配字符串结尾
[abc] 复选集定义,匹配字母 a 或 b 或 c
[abc][vz] 复选集定义,匹配字母 a 或 b 或 c,后面跟着 v 或 z
[^abc] 当插入符 ^ 在中括号中以第一个字符开始显示,则表示否认模式。此模式匹配全部字符,除了 a 或 b 或 c
[a-d1-7] 范围匹配,匹配字母 a 到 d 和数字从 1 到 7 之间,但不匹配 d1
XZ 匹配 X 后直接跟着 Z
X\ Z 匹配 X 或 Z

元字符

元字符是一个预约义的字符。

正则表达式 描述
\d 匹配一个数字,是 [0-9] 的简写
\D 匹配一个非数字,是 [^0-9] 的简写
\s 匹配一个空格,是 [ \t\n\x0b\r\f] 的简写
\S 匹配一个非空格
\w 匹配一个单词字符(大小写字母、数字、下划线),是 [a-zA-Z_0-9] 的简写
\W 匹配一个非单词字符(除了大小写字母、数字、下划线以外的字符),等同于 [^\w]

限定符

限定符定义了一个元素能够发生的频率。

正则表达式 描述 举例
* 匹配 >=0 个,是 {0,} 的简写 X* 表示匹配零个或多个字母 X,.*表示匹配任何字符串
+ 匹配 >=1 个,是 {1,} 的简写 X+ 表示匹配一个或多个字母 X
? 匹配 1 个或 0 个,是 {0,1} 的简写 X? 表示匹配 0 个或 1 个字母 X
{X} 只匹配 X 个字符 \d{3} 表示匹配 3 个数字,.{10}表示匹配任何长度是 10 的字符串
{X,Y} 匹配 >=X 且 <=Y 个 \d{1,4} 表示匹配至少 1 个最多 4 个数字
*? 若是 ? 是限定符 *+?{} 后面的第一个字符,那么表示非贪婪模式(尽量少的匹配字符),而不是默认的贪婪模式

分组和反向引用

小括号 () 能够达到对正则表达式进行分组的效果。

模式分组后会在正则表达式中建立反向引用。反向引用会保存匹配模式分组的字符串片段,这使得咱们能够获取并使用这个字符串片段。

在以正则表达式替换字符串的语法中,是经过 $ 来引用分组的反向引用,$0 是匹配完整模式的字符串(注意在 JavaScript 中是用 $& 表示);$1 是第一个分组的反向引用;$2 是第二个分组的反向引用,以此类推。

示例:

package com.baizhi.test;

public class RegexTest {

    public static void main(String[] args) {
        // 去除单词与 , 和 . 之间的空格
        String Str = "Hello , World .";
        String pattern = "(\\w)(\\s+)([.,])";
        // $0 匹配 `(\w)(\s+)([.,])` 结果为 `o空格,` 和 `d空格.`
        // $1 匹配 `(\w)` 结果为 `o` 和 `d`
        // $2 匹配 `(\s+)` 结果为 `空格` 和 `空格`
        // $3 匹配 `([.,])` 结果为 `,` 和 `.`
        System.out.println(Str.replaceAll(pattern, "$1$3")); // Hello, World.
    }
}

上面的例子中,咱们使用了 [.] 来匹配普通字符 . 而不须要使用 [\\.]。由于正则对于 [] 中的 .,会自动处理为 [\.],即普通字符 . 进行匹配。

否认先行断言(Negative lookahead)

咱们能够建立否认先行断言模式的匹配,即某个字符串后面不包含另外一个字符串的匹配模式。

否认先行断言模式经过 (?!pattern) 定义。好比,咱们匹配后面不是跟着 "b" 的 "a":

a(?!b)

指定正则表达式的模式

能够在正则的开头指定模式修饰符。

  • (?i) 使正则忽略大小写。
  • (?s) 表示单行模式("single line mode")使正则的 . 匹配全部字符,包括换行符。
  • (?m) 表示多行模式("multi-line mode"),使正则的 ^$ 匹配字符串中每行的开始和结束。

Java 中的反斜杠

反斜杠 \ 在 Java 中表示转义字符,这意味着 \ 在 Java 拥有预约义的含义。

这里例举两个特别重要的用法:

  • 在匹配 .{[(?$^* 这些特殊字符时,须要在前面加上 \\,好比匹配 . 时,Java 中要写为 \\.,但对于正则表达式来讲就是 \.
  • 在匹配 \ 时,Java 中要写为 \\\\,但对于正则表达式来讲就是 \\

注意:Java 中的正则表达式字符串有两层含义,首先 Java 字符串转义出符合正则表达式语法的字符串,而后再由转义后的正则表达式进行模式匹配。

正则表达式常见应用示例

中文的匹配

[\u4e00-\u9fa5]+ 表明匹配中文字。

public static void test3(){
        String str = "这里有个新手易范的错误,就是正angongsi";
        Pattern pattern = Pattern.compile("[\\u4e00-\\u9fa5]+");
        Matcher matcher = pattern.matcher(str);
        while (matcher.find()) {
            System.out.println(matcher.group());
        }
    }

数字范围的匹配

好比,匹配 1990 到 2017。

注意:这里有个新手易范的错误,就是正则 [1990-2017],实际这个正则只匹配 01279 中的任一个字符。

正则表达式匹配数字范围时,首先要肯定最大值与最小值,最后写中间值。

正确的匹配方式:

public static void test4(){
        String str = "1990\n2010\n2017\nsdfgadfggadfgdfgdfgafdgasfdga\n1998";
        // 这里应用了 (?m) 的多行匹配模式,只为方便咱们测试输出
        // "^1990$|^199[1-9]$|^20[0-1][0-6]$|^2017$" 为判断 1990-2017 正确的正则表达式
        Pattern pattern = Pattern.compile("(?m)^1990$|^199[1-9]$|^20[0-1][0-6]$|^2017$");
        Matcher matcher = pattern.matcher(str);
        while (matcher.find()) {
            System.out.println(matcher.group());
        }
    }

img 标签的匹配

好比,获取图片文件内容,这里咱们考虑了一些不规范的 img 标签写法:

public static void test5(){
         String str = "<img  src='aaa.jpg' /><img src=bbb.png/><img src=\"ccc.png\"/>" +
                    "<img src='ddd.exe'/><img src='eee.jpn'/>";
            // 这里咱们考虑了一些不规范的 img 标签写法,好比:空格、引号
            Pattern pattern = Pattern.compile("<img\\s+src=(?:['\"])?(?<src>\\w+.(jpg|png))(?:['\"])?\\s*/>");
            Matcher matcher = pattern.matcher(str);
            while (matcher.find()) {
                System.out.println(matcher.group("src"));
            }
    }

邮箱匹配

邮箱匹配的正则的写法有不少,这里给出一种参考的写法。

合法E-mail地址:

  1. 必须包含一个而且只有一个符号“@”
  2. 第一个字符不得是“@”或者“.”
  3. 不容许出现“@.”或者.@
  4. 结尾不得是字符“@”或者“.”
  5. 容许“@”前的字符中出现“+”
  6. 不容许“+”在最前面,或者“+@”

等等

示例代码

public static void test6(){
         String check = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";  
         Pattern regex = Pattern.compile(check);  
         Matcher matcher = regex.matcher("dffdfdf@qq.com");  
         boolean isMatched = matcher.matches();  
         System.out.println(isMatched); 
    }

手机号匹配

public static void test7(){
        String check = "^((13[0-9])|(15[^4])|(18[0-9])|(17[0-9])|(147))\\d{8}$"; 
         Pattern regex = Pattern.compile(check); 
         Matcher matcher = regex.matcher("18638693953"); 
         boolean isMatched = matcher.matches(); 
         System.out.println(isMatched); 
    }

url匹配

public static void test8(){
        String url = "http://www.lubingyang.com/";
        String regex = "(https?://(w{3}\\.)?)?\\w+\\.\\w+(\\.[a-zA-Z]+)*(:\\d{1,5})?(/\\w*)*(\\??(.+=.*)?(&.+=.*)?)?";
        boolean isMatched = Pattern.matches(regex, url);
        System.out.println(isMatched);
    }

求点赞,求关注,求转发

欢迎关注本人公众号:鹿老师的Java笔记,将在长期更新Java技术图文教程和视频教程,Java学习经验,Java面试经验以及Java实战开发经验。