14.正则表达式

教程 阿布都的都 ⋅ 于 2023-01-06 10:35:35 ⋅ 710 阅读

正则表达式

正则表达式(Regular Expression、regex或regexp,缩写为RE),描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。

1 正则表达式语法

在java语言中,java.util.regex.Pattern类是正则表达式的编译表示形式。 相应的语法规则,在此类的API中定义。

1.1 字符

x               字符x,任意字符代表其本身
\\              反斜线字符(\)
\t              制表符 ('\u0009')
\n              换行符 ('\u000A') 
\r              回车符 ('\u000D')
\f              换页符 ('\u000C') 

1.2 字符类

[abc]           匹配a、b 或 c中的一个字符(简单类)
[^abc]          任何字符,除了 a、b 或 c(否定) 
[a-zA-Z]        a 到 z 或 A 到 Z中的一个字符,两头的字母包括在内(范围) 
[a-d[m-p]]      a 到 d 或 m 到 p:[a-dm-p](并集) 
[a-z&&[def]]    d、e 或 f(交集) 

1.3 预定义字符类

.               匹配任意字符
\d              匹配数字字符,相当于[0-9]
\D              匹配非数字字符,相当于[^0-9] 
\s              空白字符,相当于[ \t\n\x0B\f\r] ,匹配所有空白符,包括换行
\S              非空白字符:[^\s] 
\w              单词字符:[a-zA-Z_0-9] ,匹配字母、数字、下划线
\W              非单词字符:[^\w] 

1.4 边界匹配器(定位符)

^               行的开头 
$               行的结尾 
\b              单词边界  匹配一个位置 0宽度
\B              非单词边界 

1.5 限定符

X?              X,一次或一次也没有。匹配前面的子表达式X零次或一次。
X*              X,零次或多次 
X+              X,一次或多次 
X{n}            X,恰好 n 次 
X{n,}           X,至少 n 次 
X{n,m}          X,至少 n 次,但是不超过 m 次 

1.6 捕获组

() 表示捕获分组,() 会把每个分组里的匹配的值保存起来, 多个匹配值可以通过数字 n 来查看(n 是一个数字,表示第 n 个捕获组的内容)。

捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:

​ 1 ((A)(B(C)))

​ 2 (A)

​ 3 (B(C))

​ 4 (C)

组零始终代表整个表达式。

2 正则表达式的使用(重点)

下面从常见的几个使用场景,简单介绍正则表达式的使用方法。

1、正则表达式的校验功能

String类中的API:
public boolean matches(String regex)
    判断此字符串是否与给定的正则表达式匹配

示例:

数据校验 -- 例如校验用户输入的邮箱是否合法
// 通用的邮箱标准:长度不限,可以使用英文(包括大小写)、数字、点号、下划线、减号,首字母必须是字母或数字。
String regex = "^[a-z0-9A-Z]+[-|a-z0-9A-Z._]+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-z]{2,}$";
// 下面四个邮箱都是符合规则的有效数据
String email1 = "xxxyyy@zzz.com.cn";
String email2 = "xxx-yyy@zzz.com";
String email3 = "xxx_yyy@zzz.cn";
String email4 = "88888@qq.com";
System.out.println(email1.matches(regex)); 
System.out.println(email2.matches(regex));
System.out.println(email3.matches(regex));
System.out.println(email4.matches(regex));

2、正则表达式的替换功能

String类中的API:
public String replaceAll(String regex, String replacement)
    将此字符串中匹配给定正则表达式的所有子串替换
    参数1表示正则表达式,符合此规则的子串将被替换
    参数2表示要要替换每个匹配项的字符串

public String replaceFirst(String regex, String replacement)
    将此字符串中匹配给定正则表达式的第一个子串替换

示例:

// 将下面文本中的手机号码全部使用****代替
String str = "张三的电话号码是:13877778888,李四的电话号码是:13966669999,王五的电话号码是:18898765432。";
String regex = "1[3456789]\\d{9}";
String repStr = str.replaceAll(regex, "****");
System.out.println(repStr);
// 输出结果:张三的电话号码是:****,李四的电话号码是:****,王五的电话号码是:****。

// ------------------------------
// 将下面文本中的第一个手机号码使用****代替
String str = "张三的电话号码是:13877778888,李四的电话号码是:13966669999,王五的电话号码是:18898765432。";
String regex = "1[3456789]\\d{9}";
String repStr = str.replaceFirst(regex, "****");
System.out.println(repStr);
// 输出结果:张三的电话号码是:****,李四的电话号码是:13966669999,王五的电话号码是:18898765432。

3、正则表达式的拆分功能

String类中的API:
public String[] split(String regex)
    使用指定的正则表达式将此字符串拆分,返回拆分后得到的字符串数组
    注意:结尾的空字符串不包含在结果数组中。

例如:
    字符串"boo:and:foo",使用正则表达式":"进行拆分,得到{"boo", "and", "foo"}
    字符串"boo:and:foo",使用正则表达式"o"进行拆分,得到{"b", "", ":and:f"}
        中间连续的两个"o"匹配,拆分出一个空串,而结尾处的两个"o"匹配,得到的空串不会保留。

示例:

String str = "11 22   33  44     55";
// 将上面文本中的有效数据拆分出来,注意:数据中间的空格数量不确定。
String[] strs = str.split("\\s+"); // 按照一个或多个空白字符拆分
System.out.println(Arrays.toString(strs)); // [11, 22, 33, 44, 55]

4、正在表达式的获取功能

在java.util.regex 包主要包括以下三个类:

  • Pattern 类:

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

  • Matcher 类:

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

  • PatternSyntaxException:

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

典型使用顺序如下:

Pattern p = Pattern.compile("a*b"); // 将字符串形式的正则表达式编译为Pattern类的实例
Matcher m = p.matcher("aaaaab"); // 创建一个匹配此模式的给定输入的匹配器
boolean b = m.matches(); // 判断输入的字符串是否匹配此模式

在Matcher 类中,有如下三个常用方法:

public boolean matches()
    尝试将整个字符串与模式匹配

public boolean find()
    尝试查找与模式匹配的输入序列的下一个子序列
public String group()
    返回上一个匹配项匹配的输入子序列

示例:

// 将下面文本中的手机号码全部获取出来
String str = "张三的电话号码是:13877778888,李四的电话号码是:13966669999,王五的电话号码是:18898765432。";
// 获取正则表达式模式对象
Pattern pattern = Pattern.compile("1[3456789]\\d{9}");
// 根据模式对象获取匹配器对象
Matcher matcher = pattern.matcher(str);
// 如果可以找到匹配的子串
while (matcher.find()) {
    // 获取匹配的子串
    String subStr = matcher.group();
    System.out.println(subStr);
}

5、捕获组的使用

示例:

// 现得到如下的字符串:
String s = "我..我....我.我...我.要.要...要...要..要...要.学..学.学...学.学.编...编.编..编...编...程程..程..程";
// 请还原出其中的有效信息:我要学编程
// 首先替换掉所有的点
s = s.replaceAll("\\.", "");
// 再匹配其中的叠词(即重复出现的字符),只保留一份
s = s.replaceAll("(.)\\1+", "$1"); 
// 将任意字符放入组中,\1表示组1(即该字符)再次出现一次或多次;第二个参数$1表示引用组1的内容。
System.out.println(s);

常用正则表达式

汉字:^[\u4e00-\u9fa5]$

英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$

Email地址:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$

URL:/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/

IP 地址:/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/

身份证号:var p = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
版权声明:原创作品,允许转载,转载时务必以超链接的形式表明出处和作者信息。否则将追究法律责任。来自海汼部落-阿布都的都,http://hainiubl.com/topics/75995
回复数量: 0
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,可用Emoji的自动补全, 在输入的时候只需要 ":" 就可以自动提示了 :metal: :point_right: 表情列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif,教程
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter