携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
介绍
正则表达式 regular expression,简称 regex。由一些字母、字符以及特殊字符组成的字符串,通过该字符串去匹配一些子串,或是搜索子串,或是替换子串,来完成一系列的操作。
JDK API 中 java.util.regex 包,提供了 Java 自带的正则表达式的接口、类和异常类。
核心类主要是 Pattern 和 Matcher 。
Pattern 类被 final 修饰的,说明该类中的所有方法可以使用,但不能被重写,该类中提供了正则所有的规则。我们可以根据规则制定出所需的模式来。
Matcher 类也是被 final 修饰的,主要提供一系列字符串匹配查询的方法。
以下是正则中的保留字符:
| 保留字符 | 说明 | |
|---|---|---|
| () | 把圆括号内外的表达式区分开。 | |
| [] | 方括号内的字符之间是 “或” 的关系。 | |
| {} | 花括号内填写的数字,表示表达式匹配的次数。 | |
| 对竖线前后字符做 “或” 运算。 | ||
| - | 横线前后的字符,表示两个字符之间的所有连续字符。 | |
| \ | 反斜杠对保留字符做转义,保留自身符号。 |
以下是相对常用的规则
| 匹配符 | 说明 |
|---|---|
| [abc] | 包含字母 a 或 b 或 c。 |
| [^abc] | 不包含字母 a 或 b 或 c 的其他字母。 |
| [a-zA-Z] | 包含字母 a - z 和 A - Z 范围内的。 |
| [0-9] | 包含 0 - 9 数字的。 |
| . | 表示任意字符(除换行符 \n 外) 。 |
| \d | 等价于 [0-9]。 |
| \s | 表示任意空白符,等价于[ \t\n\x0B\f\r] 这些符号。 |
| \S | 表示除空白符以外的所有字符。 |
| \w | 等价于 [a-zA-Z_0-9]。 |
以下限定符的说明:
| 符号 | 说明 |
|---|---|
| ? | 是否出现。 |
| * | 出现 0 或多次。 |
| + | 出现 1 或多次。 |
| {n} | n 表示出现的次数,表达式出现 n 次。 |
| {n,} | 表达式至少出现 n 次。 |
| {n,m} | 表达式至少出现 n 次,最多出现 m 次。 |
现在给出这样一个192.168.9字符串,来书写能匹配的正则表达式:
如果是ip,第一位不能是0,所以[1-9],第二位和第三位可以是 [0-9] 的数字,但是第二位和第三位可以有也可以没有,所以我们限定出现次数至少 0 次最多 2 次
,这里用 点 分割,但是在正则表达式中点表示除换行符以外的所有字符,所以我们需要转换 \.0 - 9 的数字我们可以采用 \d 符号来表示更为简化,当然也可以使用 \p{Digit} 这是 POSIX 字符类,在使用时符号前面还需要再加一个 `` 转义才可以
答案:[1-9][0-9]{0,2}\\.\\d[1,3]\\.\\{Digit}
ip 地址,如果整个字符串都要匹配,那么就需要这样写
[a-z]{2}:([1-9][0-9]{0,2}\.\d{1,3}\.\p{Digit}{1,3}\.\d{1,3},?)+
那么在 Java 中如何使用正则表达式完成匹配操作呢?
主要使用 java.util.regex 包中的 Pattern 和 Matcher 类进行操作。
Matcher 类没有提供构造方法,那么它的实例如何获取呢?
可以通过 Pattern 类中的 matcher() 方法来获取哦。 😮
public Matcher matcher(CharSequence input),该方法不是静态方法,必须先获取到 Pattern 实例后,才能调用。
Matcher 类中常用的匹配方法: 👇
| 方法 | 说明 |
|---|---|
| public boolean matches() | 提供的正则表达式完成匹配时返回 true,否则返回 false。 |
| public boolean find() | 提供的正则表达式只要有部分匹配就返回 true。 |
| public String group() | 提取匹配的子串信息。 |
| public int start() | 返回匹配子串的开始索引。 |
| public int end() | 返回匹配子串的结束索引。 |
使用:
根据给定的正则表达式获取 Pattern 类对象 Pattern p = Pattern.compile(regex);
通过 Pattern 类中的 matcher() 方法获取 Matcher 类对象 Matcher m = p.matcher(input);
当输入字符串中的内容完全匹配,则打印输出 if(m.matches())
当输入的字符串只能部分匹配时,则一部分一部分打印输出 while(m.find())
import......
public class TestRegex {
/**
* 正则表达式进行数据验证的操作
* @param regex 正则表达式
* @param input 匹配的数据信息
*/
public void method1(String regex,String input) {
// 根据给定的正则表达式获取 Pattern 类对象
Pattern p = Pattern.compile(regex);
// 通过 Pattern 类中的 matcher() 方法获取 Matcher 类对象
Matcher m = p.matcher(input);
// 当输入字符串中的内容完全匹配,则打印输出
if(m.matches()) {
System.out.println(m.group());
}else {
// 当输入的字符串只能部分匹配时,则一部分一部分打印输出
while(m.find()) {
System.out.println(m.group()+" start index: "+m.start()+" end index: "+m.end());
}
}
}
public static void main(String[] args) {
TestRegex tr = new TestRegex();
tr.method1("[1-9][0-9]{0,2}\.\d{1,3}\.\p{Digit}{1,3}\.\d{1,3}", "ip:192.168.9.12,127.0.0.1");
tr.method1("[a-z]{2}:([1-9][0-9]{0,2}\.\d{1,3}\.\p{Digit}{1,3}\.\d{1,3},?)+", "ip:192.168.9.12,127.0.0.1");
}
}
正则表达式搜索和替换
我们也可以通过正则表达式进行搜索和替换操作,Matcher 类中提供了替换的方法如下:
public Matcher appendReplacement(StringBuffer sb, String replacement)public StringBuffer appendTail(StringBuffer sb)
public void method2() {
// 提供字符串,将字符串中的子串java,奇数为小写,偶数为大写
String s = "Java jAva test java JAVa JaVa hello low JavA JAVA CoCo";
// flags 标记位设置为 Pattern.CASE_INSENSITIVE,表示匹配 java 时忽略大小写。
Pattern p = Pattern.compile("java",Pattern.CASE_INSENSITIVE);
// 将字符串根据模式进行匹配
Matcher m = p.matcher(s);
// 创建字符串缓冲区
StringBuffer buffer = new StringBuffer();
int i = 0;
while(m.find()) {
i++;
// 将找到的 java 字符串进行替换 m.appendReplacement(buffer, i%2==0?"JAVA":"java");
}
// 将数据追加放入字符串缓冲区中 m.appendTail(buffer);
// 将字符串缓冲区打印输出 System.out.println(buffer);
}
public static void main(String[] args) {
TestRegex tr = new TestRegex(); tr.method2();
}
字符串的匹配、查找、替换和分割
正则表达式是匹配字符串的一类逻辑式,通过代表特定含义的保留字符,能够描述符合规则的一组字符串,在字符串中运用正则表达式常用于字符串的分割与匹配校验。
字符串的匹配、查找、替换和分割是企业项目中不可缺少的部分,经常需要进行一些列处理后进行存储。
然而自付出的匹配、查找、替换和分割,往往都是离不开正则表达式的使用。
以下是 String 类中提供需要使用正则表达式的方法:
| 方法 | 说明 |
|---|---|
| public boolean matches(String regex) | 根据 regex 进行匹配,能匹配返回 true,否则返回 false。 |
| public String replaceFirst(String regex, String replacement) | 根据 regex 进行查找,找到后进行替换第一个匹配的字符串。 |
| public String replaceAll(String regex, String replacement) | 根据 regex 进行查找,找到后进行替换全部匹配的字符串。 |
| public String[] split(String regex) | 根据 regex 分割字符串,将分割后的数据存储在 String 数组中。 |
接下来,我们一个个来看一下:
-
String 类中提供的 matches() 方法。
该方法其实源码中访问的是 Pattern.matches(regex, str),使用代码如下:
String str = "abcdeeeabcefg";
str.matches("(abc.*)+"); --> 返回 true
-
String 类中提供的 replaceFirst() 和 replaceAll() 方法。
这两个替换方法其实源码中访问的是:
Pattern.compile(regex).matcher(str).replaceFirst(replacement)
Pattern.compile(regex).matcher(str).replaceAll(replacement)
使用代码如下:
String str = "abcdeeeabcefg";
str.replaceFirst("abc", "小桃子"); --> 返回字符串:小桃子deeeabcefg
str.replaceAll("ab.{2}", "企鹅"); --> 返回字符串:企鹅eee企鹅fg
-
String 类中提供的 split () 方法
分割方法在源码中也是访问 Pattern 类中的方法,Pattern.compile(regex).split(str) ,使用代码如下:
String str2 = "hello|你好|123|test|java";
String[] ss = str2.split("\|");
str2 = "hello,你好,123,test,java";
ss = str2.split(",");
符号中 “ | ” 需要转义才能使用,不过也可以这样写 \s*\|\s* ,而 “ , ” 无须转义直接可用。
对于字符串的分割操作,split() 方法的执行效果是比较低的。
在企业项目中,我们对字符串进行分割会使用的是 StringTokenizer 类,它存放在 java.util 包中。
StringTokenizer 类中空格是默认分割符:
StringTokenizer st = new StringTokenizer("this is a string");
如果是其他的分割符,则需要指定:
StringTokenizer st = new StringTokenizer("this|is|a|string", "|");
StringTokenizer st = new StringTokenizer("this,is,a,string", ",");