入门案例
提供了丰富的语法内容,正则表达式是分析检索文本内容的利器。
public class demo {
public static void main(String[] args) {
String content = "1992年我在广场吃炸鸡啊";
String regex = "\\d\\d\\d\\d";
//获取模式对象 pattern
Pattern pattern = Pattern.compile(regex);
//获取matcher构造器
Matcher matcher = pattern.matcher(content);
while(matcher.find()) {
System.out.println(matcher.group(0));
}
}
}
正则表达式底层实现
public class demo {
public static void main(String[] args) {
String content = "台上深情讲述、精彩1998纷呈,台下掌声雷动、气氛热烈,三十余位来自不同行业、不同领域,用奋斗承担青春使命之责、用奋斗谱写青春华章的杰出1998代表,围绕“青春奋斗”与莘莘学子对话青春、共叙成长,共赴一场激荡心灵的青春1998嘉年华。";
// 1、\\d代表任意数字
String regex = "\\d\\d\\d\\d";
// 2、获取模式对象 pattern 即正则表达式对象
Pattern pattern = Pattern.compile(regex);
// 3、创建匹配器 matcher , 按照正则表达式的规则去匹配文本内容
Matcher matcher = pattern.matcher(content);
// 4、开始匹配
while(matcher.find()) { // 寻找文本中与正则表达式匹配的内容,如果找到就返回true,否则返回false
//该语句在正则表达式没有分组的情况下是固定写法 , 都是 group(0)
System.out.println(matcher.group(0));
//底层实现
// matcher 类 , 有属性int groups[] , oldLast
// 在每次寻找过程中, 都要将符合正则表达式规定的规则的文本的开始索引存放到 groups[0]
// 将末尾索引存放到 groups[1]。可以debug一下, 查看这个数组的变化,来验证
// 调用group方法, 是将这两个索引之间的内容toString
// 分组情况下写法,假设分了三组,写多了会抛出数组越界异常
// while (matcher.find()) {
// System.out.println(matcher.group(0)); // 实际返回的是groups [0] - groups[1]
// System.out.println(matcher.group(1)); // 实际返回的是groups [2] - groups[3]
// System.out.println(matcher.group(2)); // 实际返回的是groups [4] - groups[5]
// }
// group 方法源码
// public String group(int group) {
// if (first < 0)
// throw new IllegalStateException("No match found");
// if (group < 0 || group > groupCount())
// throw new IndexOutOfBoundsException("No group " + group);
// if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
// return null;
// return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
// }
}
}
}
元字符
转义字符 \\
说明: 在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义符号
则检索不到结果,甚至会报错的。
需要用到转义符号的字符有以下:*+()$/\?[]^{}
匹配符
符号 | 符号 | 示例 | 解释 |
[ ] | 可接收的字符列表 | [efgh.!] | e、f、g、h、. 、!中的任意一个字符 注意:中括号里的点号,感叹号不用转义。即中括号中的字符不需要转义 |
[^ ] | 不可接收的字符列表 | [^abc] | 除a、b、c之外的任意一个字符,包括数字和特殊符号 |
- | 连字符 | A-Z | 任意单个大写字母 |
符号 | 含义 | 示例 | 说明 | 匹配输入 |
. | 匹配除了 \n以外的任何字符 | a..b | 以a开头,b结尾,中间包括2个任意字符长度为4的字符串 | aaab、aefb、a35b、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 |
\\s | 匹配任何空白符 | \\s | \\t\\n\\r666 | |
\\S | 匹配任何非空白符 | \\S | \\t\\n\\r666 |
1.[a-z] 说明:
[a-z] 表示可以匹配a-z中任意一个字符,比如 [a-z] 、 [A-Z] 去匹配 a11c8 会得么结果?
2.java正则表达式默认是区分字母大小写的,如何实现不区分大小写
(?i)abc 表示abc都不区分大小写a(?i)bc 表示bc不区分大小写a((?i)b)c 表示只有b不区分大小写
Pattern pat = Pattern.compile(regEx, Pattern.CASE INSENSITIVE);\\不区分大小写
[A-Z] 表示可以匹配A-Z中任意一个字符.
[0-9] 表示可以匹配0-9中任意一个字符。
选择匹配符
在匹配某个字符串的时候是选择性的,即:既可以匹配这个,又可以匹配那个,这时要用到选择匹配符号
符号 | 符号 | 示例 | 解释 |
| | 匹配“|”之前或之后的表达式 | ab|cd | ab或者cd |
正则限定符
符号 | 含义 | 示例 | 说明 | 匹配输入 |
* | 指定字符重复0次或n次(无要求)零到多 | (abc)* | 仅包含任意个abc的字符串,等效于\w* | abc、abcabc |
+ | 指定字符重复1次或n次(至少一次)1到多 | m+(abc)* | 以至少1个m开头,后接任意个abc的字符串 | |
? | 指定字符重复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个匹配 | [abcd]{3,} | 由abcd字母组成的任意长度不小于3的字符串 | aab、dbc、aaadbc |
{n,m} | 指定至少n个但不多于m个匹配 | [abcd]{3,5} | 由abcd中字母组成的任意长度不小于3,不大于5的字符串 | abc、abcd、aaaaa、bcdab |
定位符
符号 | 含义 | 示例 | 说明 | 匹配输入 |
^ | 指定起始字符 | ^[0-9]+[a-z]* | 以至少1个数字开头,后接任意个小写字母的字符串 | 123、6aa、555edf |
$ | 指定结束字符 | ^[0-9]\\-[a-z]+$ | 以1个数字开头后接连字符“-”,并以至少1个小写字母结尾的字符串 | 1-a |
\\b | 匹配目标字符串的边界 | han\\b | 这里说的字符串的边界指的是子串间有空格,或者是目标字符串的结束位置 | hanshumahe sphan nnhan |
\\B | 匹配目标字符串非边界 | han\\B | 和\b的含义刚刚相反 | hanwolovd jklajjkkk |
分组、捕获
常用分组构造形式 | 说明 |
(pattern) | 非命名捕获。捕获匹配的子字符串。编号为零的第一个捕获是由整个正则表达式模式匹配的文本,其他捕获结果则根据做括号的顺序从1开始自动编号。 |
(?<name>pattern) | 命名捕获。将匹配的子字符串捕获到一个组名称或编号名称中。用于name的字符串不能包含任何标点符号,并且不能以数字开头,可以使用单引号代替尖括号,例如(?'name') |
特别分组(非捕获匹配)
常用分组构造形式 | 说明 |
(?:pattern) | 匹配patter但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于“or”字符(|)组合模式部件的情况有用。例如,‘industr(?:y|ies)’是比‘industry|industries’更经济的表达式 |
(?=pattern) | 它是一个非捕获匹配。例如,‘windows(?=95|98|NT|2000’匹配“windows2000”中的“Windows”,但不匹配“Windows3.1”中的“windows”. |
(?!pattern) | 该表达式匹配不处于匹配pattern的字符串的起始点的搜索字符串。它是一个非捕获匹配。例如,‘windows(?=95|98|NT|2000’匹配“Windows 3.1”中的 “Windows”,但不匹配“Windows 2000”中的“Windows”。 |
非贪婪匹配
java正则表达式默认是贪婪匹配
练习
复杂URL验证
Pattern类与Matcher类
pattern类 :
matches() 方法
直接调用静态方法Pattern.matches(string,string), 比较正则表达式regex,与content是否匹配(url判断)
Matcher类
start()方法,end () 方法
replaceall () 方法
public static void main(String[] args) {
String regex = "age";
String content = "agenameagename";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(content);
System.out.println(matcher.replaceAll("年龄"));
}
}
输出
matches () 方法
反引用
遇到去重场景非常实用
String中支持正则表达式的方法
replace () 替换
split() 截取
maches() 整体匹配验证、
练习
1.验证电子邮件格式是否合法
1.规定电子邮件规则为只能有一个@
2.@前面是用户名,可以是a-z A-Z 0-9 _-字符
3.@后面是域名,并且域名只能是英文字母,比如 sohurcom 或者 tsinghua.org.cn
写出对应的正则表达式,验证输入的字符串是否为满足规则
public static void main(String[] args) {
String regex = "[\\w-]+@([a-zA-Z]+\\.)+[a-zA-Z]+";
String content = "icando@qq.com";
boolean b = content.matches(regex);
System.out.println(b);
}
}
2.要求验证是不是整数或者小数
提示:这个题要考虑正数和负数
比如:123 -345 34.89 -87.9 -0.01 0.45 等
public static void main(String[] args) {
//问题:验证一个数是整数还是小数, 提示:需要考虑正负数
// 思路
// 1.先写出一般情况
// 2.再逐步完善
String regex = "^[+-]*([1-9]\\d*|0)(\\.\\d+)?";
String content = "-0.12";
boolean b = content.matches(regex);
System.out.println(b);
}
3.对一个url进行解析
https://www.sohucom:8080/abc/index.htm
要求得到
协议是什么?
域名是什么?
端口是什么?
文件名是什么?
public static void main(String[] args) {
String content = "http://www.baidu.com:8080/index.html";
String regex = "^([a-zA-Z]+)://([a-zA-Z.]+):(\\d+)[\\w-/]*([\\w.]+)$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(content);
if (matcher.matches()) {
System.out.println("匹配成功");
System.out.println("协议"+matcher.group(1));
System.out.println("域名"+matcher.group(2));
System.out.println("端口号"+matcher.group(3));
System.out.println("文件名"+matcher.group(4));
}
}
注意: matches方法 中, 设置了group数组的数值,即分组在content中的下标
输出