1 正则表达式概念
正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"),是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。
简单来说,正则表达式就是一个很牛逼的字符串处理工具。
正则在线工具 :
https://c.runoob.com/front-end/854/?optionGlobl=global
2 String类中的正则表达式
public class StringRegexDemo1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (true) {
System.out.println("请输入qq");
String s1 = in.nextLine();
//匹配s1中是否是6-12位数字
System.out.println(s1.matches("^[0-9]{6,12}$"));
}
}
@Test
public void test1() {
String s = "Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统";
// s = s.replaceAll("[a-zA-Z]{1,}", "hello");
s = s.replaceAll("[a-zA-Z]+", "hello");
s = s.replaceAll("\\d+", "world");
System.out.println(s);
}
@Test
public void test2() {
String s1 = "aaa,bbb,123,456,hello,word";
String[] arrs = s1.split(",");
for (int i = 0; i < arrs.length; i++) {
System.out.println(arrs[i]);
}
}
@Test
public void test3() {
String s2 = "hello12333world4567welcome34to4beijing";
String[] arrs2 = s2.split("\\d+");
for (int i = 0; i < arrs2.length; i++) {
System.out.println(arrs2[i]);
}
}
}
3 正则表达式常用类
3.1 Pattern类
pattern对象是一个正则表达式的编译表示。Pattern类没有公共构造方法。要创建一个Pattern对象,你必须首先调用其公共静态方法,它返回一个pattern对象。该方法接受一个正则表达式作为它的第一个参数。
- compile():通过正则得到一个Pattern
- matchers():方便正则表达式只是用一次,进行匹配
- matcher():产生Matcher对象,多次正则匹配,推荐使用
3.2 Matcher类
Matcher对象是对输入字符串进行解释和匹配操作的引擎。与Pattern类一样,Matcher也没有公共构造方法。你需要调用Pattern对象的matcher方法来获得一个Matcher对象。
3.2.1 索引方法
索引方法提供了有用的索引值,精确表明输入字符串在哪能找到匹配:
- public int start(): 返回以前匹配的初始索引。
- public int start(int group): 返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引
- public int end(): 返回最后匹配字符之后的偏移量。
- public int end(int group): 返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。
3.2.2 查找方法
查找方法用来检查输入字符串并返回一个布尔值,表示是否找到该模式:
- public boolean lookingAt(): 尝试将从区域开头开始的输入序列与该模式匹配。
- public boolean find(): 尝试查找与该模式匹配的输入序列的下一个子序列。
- public boolean find(int start): 重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
- public boolean matches(): 尝试将整个区域与模式匹配。
- group(): 返回上一个匹配项匹配的输入子序列。
- group(int group): 返回上一个匹配操作期间给定组捕获的输入子序列。
3.2.3 替换方法
替换方法是替换输入字符串里文本的方法:
- public Matcher appendReplacement(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 class RegexDemo1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
//
Pattern pattern = Pattern.compile("^[0-9]{5,12}$"); //正则的编译对象
while (true) {
System.out.println("请输入qq");
String s1 = in.nextLine();
Matcher matcher = pattern.matcher(s1);
System.out.println(matcher.matches()); //全部匹配
// System.out.println(s1.matches("^[0-9]{5,12}$"));
}
}
@Test
public void test1() {
//正则编译对象,只匹配一次可以使用matches方法
System.out.println(Pattern.matches("^[0-9]{5,12}$", "77546313")); //正则是否全部匹配
System.out.println(Pattern.matches("^[0-9]{5,12}$", "123456")); //正则是否全部匹配
System.out.println(Pattern.matches("^[0-9]{5,12}$", "333333")); //正则是否全部匹配
Pattern pattern = Pattern.compile("^[0-9]{5,12}$");
pattern.matcher("77546313").matches();
pattern.matcher("123456").matches();
pattern.matcher("333333").matches();
}
@Test
public void test2() {
//全部匹配
Pattern pattern = Pattern.compile("\\d{5,12}");
Matcher matcher = pattern.matcher("12345a34343434");
System.out.println(matcher.matches()); //全部匹配
}
@Test
public void test3() {
//全部匹配
Pattern pattern = Pattern.compile("\\d{5,12}");
Matcher matcher = pattern.matcher("12345a34343434abc9878989");
while (matcher.find()) {//查找匹配,如果匹配返回ture
String target = matcher.group();//得到上一次匹配的子序列
System.out.println(target + "-" + matcher.start() + "-" + matcher.end()); //start得到上一个匹配的索引开始
}
}
@Test
public void test4() {
String content =
"Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。\n"
+ "Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统。\n"
+ "本教程通过简单的实例将让大家更好的了解 Java 编程语言。\n"
+ "移动操作系统 Android 大部分的代码采用 Java 编程语言编程。";
Pattern pattern = Pattern.compile("([a-zA-Z]+) | (\\d+)");
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
String target = matcher.group(2); //0:全部的正则捕获组,1:的一个小括号的正则补货组
System.out.println(target);
}
}
@Test
public void test6() {
String content =
"Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。\n"
+ "Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统。\n"
+ "本教程通过简单的实例将让大家更好的了解 Java 编程语言。\n"
+ "移动操作系统 Android 大部分的代码采用 Java 编程语言编程。";
//创建一个Pattern对象
Pattern pattern = Pattern.compile("Java");
//创建一个匹配对象
Matcher matcher = pattern.matcher(content);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
//将Java替换为java后,将最后匹配到之前的子串都添加到sb对象中
matcher.appendReplacement(sb, "java");
System.out.println("sb:" + sb);
System.out.println("---------分割线-----------");
}
//将最后匹配到的子串添加到sb中
matcher.appendTail(sb);
System.out.println("sb: " + sb);
}
}
4 正则表达式的语法
4.1 正则转义符
元符号-转义号\
\符号说明:在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义字符,否则检测不到结果,甚至会报错。
需要用到转义符的字符有:. * + ( )$ / \ ? [ ] ^ { }
*注意:在Java的正则表达式中,两个\代表其他语言中的一个*
4.2 正则表达式支持字符
正则表达式所支持的合法字符
字符 | 解释 |
---|---|
X | 字符x(x 可代表任何合法的字符) |
\0mnn | 八进制数 0mnn 所表示的字符 |
\xhh | 十六进制值 0xhh 所表示的字符 |
\uhhhh | 十六进制值 0xhhhh 所表示的 Unicode 字符 |
\t | 制表符(“\u0009”) |
\n | 新行(换行)符(‘\u000A’) |
\r | 回车符(‘\u000D’) |
\f | 换页符(‘\u000C’) |
\a | 报警(bell)符(‘\u0007’) |
\e | Escape 符(‘\u001B’) |
\cx | x 对应的的控制符。例如,\cM匹配 Ctrl-M。x 值必须为 A~Z 或 a~z 之一。 |
正则表达式中的特殊字符
特殊字符 | 说明 |
---|---|
$ | 匹配一行的结尾。要匹配 $ 字符本身,请使用\ $ |
^ | 匹配一行的开头。要匹配 ^ 字符本身,请使用\ ^ |
() | 标记子表达式的开始和结束位置。要匹配这些字符,请使用\ (和\ ) |
[] | 用于确定中括号表达式的开始和结束位置。要匹配这些字符,请使用\ [和\ ] |
{} | 用于标记前面子表达式的出现频度。要匹配这些字符,请使用\ {和\ } |
* | 指定前面子表达式可以出现零次或多次。要匹配 * 字符本身,请使用\ * |
+ | 指定前面子表达式可以出现一次或多次。要匹配 + 字符本身,请使用\ + |
? | 指定前面子表达式可以出现零次或一次。要匹配 ?字符本身,请使用\ ? |
. | 匹配除换行符\n之外的任何单字符。要匹配.字符本身,请使用 \ . |
\ | 用于转义下一个字符,或指定八进制、十六进制字符。如果需匹配\字符,请用\ \ |
| | 指定两项之间任选一项。如果要匹配丨字符本身,请使用\ |
预定字义符
预定义字符 | 说明 |
---|---|
. | 可以匹配任何字符 |
\d | 匹配 0~9 的所有数字 |
\D | 匹配非数字 |
\s | 匹配所有的空白字符,包括空格、制表符、回车符、换页符、换行符等 |
\S | 匹配所有的非空白字符 |
\w | 匹配所有的单词字符,包括 0~9 所有数字、26 个英文字母和下画线_ |
\W | 匹配所有的非单词字符 |
方括号表达式
方括号表达式 说明 表示枚举 例如 [abc]表示 a、b、c 其中任意一个字符; [gz]表示 g、z 其中任意一个字符 表示范围:- 例如 [a-f]表示 a~f 范围内的任意字符; [\u0041-\u0056]表示十六进制字符 \u0041 到 \u0056 范围的字符。范围可以和枚举结合使用,如 [a-cx-z],表示 ac、xz 范围内的任意字符 表示求否:^ 例如 [^abc]表示非 a、b、c 的任意字符; [^a-f]表示不是 a~f 范围内的任意字符 表示“与”运算:&& 例如 [a-z&&[def]]是 a~z 和 [def] 的交集,表示 d、ef[a-z&&^bc]]是 a~z 范围内的所有字符,除 b 和 c 之外[ad-z] [a-z&&[m-p]]是 a~z 范围内的所有字符,除 m~p 范围之外的字符 表示“并”运算 并运算与前面的枚举类似。例如 [a-d[m-p]]表示 [a-dm-p]
补充:
Java正则表达式默认是区分字母大小写的,如要实现不区分大小写
(?i)abc表示abc都不区分大小写
a(?i)bc表示bc不区分大小写
a((?i)b)c表示只有b不区分大小写
Pattern pattern=Pattern.compile(regStr,Pattern.CASE_INSENSITIVE);
//当创建Pattern对象时,指定Pattern.CASE_INSENSITIVE,表示匹配不区分字母大小写
细节:Java匹配默认贪婪匹配,即尽可能匹配多的,比如"a{3,4}“,表示匹配aaa或者aaaa,但是优先匹配aaaa,例如原字符串中包括"aaaaaa”,匹配"a{3,4}“时,会找到"aaaa”
4.3 捕获组(capture group)
从正则表达式左侧开始,每出现一个左括号"("记做一个分组,分组编号从 1 开始。0 代表整个表达式。常用分组构造形式(pattern)
对于时间字符串:2017-04-25,表达式如下
(\d{4})-((\d{2})-(\d{2}))
有 4 个左括号,所以有 4 个分组:
编号 | 捕获组 | 匹配 |
---|---|---|
0 | (\d{4})-((\d{2})-(\d{2})) | 2017-04-25 |
1 | (\d{4}) | 2017 |
2 | ((\d{2})-(\d{2})) | 04-25 |
3 | (\d{2}) | 04 |
4 | (\d{2}) | 25 |
5 正则表达式的常见应用
1. 验证字符串是否全是汉字
Pattern pattern=Pattern.compile(“^ [\u0391-\uffe5]+$”);
2. 验证字符串是否是邮编
Pattern pattern=Pattern.compile(“^\d{6}$”);
3. 验证字符串是否是QQ号码
Pattern pattern=Pattern.compile(“^ [1-9]d{4,9}$”);
4. 验证字符串是否是手机号码 (要求:必须以13,14,15,18开头的11位数)
Pattern pattern=Pattern.compile(“^1[3|4|5|8]\d{9}$”);
5. 验证字符串是否是url
Pattern pattern=Pattern.compile(“^((http|https) : //)([\w-]+\.)+[\w-]+(\/[\w-?=&/%.#]*)?$”);