一.正则表达式概述
正则表达式用于操作字符串数据。通过一些特定的符号来体现的。所以我们为了掌握正则表达式,必须要学习一些符号。
正则表达式虽然简化书写,但是阅读性差。所以开发时一般是将正则表达式封装到方法里,然后将要操作的字符串传递到方法里操作。
二. 正则表达式常用规则
1.字符类
符号 |
意义 |
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(交集) |
[a-z&&[^bc]] |
a 到 z,除了 b和 c:[ad-z](减去) |
[a-z&&[^m-p]] |
a 到 z,而非 m到 p:[a-lq-z](减去) |
2.预定义字符类
符号 |
意义 |
. |
任何字符(与行结束符可能匹配也可能不匹配) |
\d |
数字:[0-9] |
\D |
非数字: [^0-9] |
\s |
空白字符:[ \t\n\x0B\f\r] |
\S |
非空白字符:[^\s] |
\w |
单词字符:[a-zA-Z_0-9] |
\W |
非单词字符:[^\w] |
3. Greedy数量词
X? |
X,一次或一次也没有 |
X* |
X,零次或多次 |
X+ |
X,一次或多次 |
X{n} |
X,恰好 n 次 |
X{n,} |
X,至少 n 次 |
X{n,m} |
X,至少 n 次,但是不超过 m 次 |
三. 常见的正则操作
1. 匹配
匹配时一般用String类中的matches(regex)方法,此方法会返回一个boolean值。
2. 切割
使用String类中的方法:String[] split(String regex).
遇到特殊符号,如"。"作为分割点时,可以使用双斜杠"\\.",将特殊符号转换为普通字符。
组的概念:((A)(B)(C)),看括号左边,从左至右编号,组零始终代表整个表达式。
3. 替换
使用String类中的replaceAll()方法
4.获取
将字符串中符合规则的子串取出。
步骤:
- 将正则表达式封装成对象。Pattern p = Pattern.compile("a*b");
- 让正则对象与要操作的字符串相关联。Matcher m = p.matcher("aaaaab");
- 通过Matcher匹配器对象的方法对字符串进行操作。boolean b = m.matches();
代码示例1:定义一个功能对QQ号进行校验。长度为5~15,只能是数字,0不能开头。
<span style="font-size:18px;">//匹配练习1
public class RegexDemo {
public static void main(String[] args) {
// checkQQ(qq);
//使用正则表达式
String qq = "416757768232";
String regex = "[1-9][0-9]{4,14}";
// boolean b = qq.matches(regex);
// System.out.println(qq+":"+b);
String str = "aoob";
String reg = "ao{0,1}b";
boolean b = str.matches(reg);
System.out.println(str+":"+b);
}
/*
* 不用正则表达式的常规方法
*/
public static void checkQQ(String qq){
int len = qq.length();
if(len>=5 && len<=15){
if(!qq.startsWith("0")){
try{
long l = Long.parseLong(qq);
System.out.println(l+":正确");
}catch(NumberFormatException e){
System.out.println(qq+":含有非法字符!");
}
}else{
System.out.println(qq+":不能0开头");
}
}else{
System.out.println(qq+":长度不符合条件!");
}
}
}
</span>
代码示例二:正则表达式的常见操作
<span style="font-size:18px;">import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo2 {
public static void main(String[] args){
/*
* 正则表达式对字符串的常见操作:
* 1.匹配
* String类中的matches()方法
* 2.切割
* split()
* 遇到特殊符号,如"。"作为分割点时,可以使用双斜杠"\\.",将特殊符号转换为普通字符。
*
* 组:((A)(B)(C)),看括号左边,从左至右编号,组零始终代表整个表达式。
* 3.替换
* 使用String类中的replaceAll()方法
* 4.获取
* //将正则进行对象的封装
* Pattern p = Pattern.compile("a*b");
//通过正则对象的matcher方法字符串相关联,获取要对字符串操作的匹配器对象Matcher
Matcher m = p.matcher("aaaaab");
//通过Matcher匹配器对象的方法对字符串进行操作。
boolean b = m.matches();
*
*
* 匹配,切割,替换,获取这些动作,底层都是Pattern的方法,
* 描述正则就这一个对象。只是封装在String类操作更方便。
*/
// functionDemo_1();
// functionDemo_2();
// functionDemo_3();
functionDemo_4();
}
//获取
public static void functionDemo_4() {
String str = "da jia hao,ming tian bu fang jia!";
String regex = "\\b[a-z]{3}\\b";//注意,要加上单词边界
//1.将正则封装成对象
Pattern p = Pattern.compile(regex);
//2.通过正则对象获取操作字符串的Matcher匹配器
Matcher m = p.matcher(str);
//3.查找。find();
System.out.println(str);
while(m.find()){//先查找匹配。
System.out.println(m.group());//查找后才能获取匹配的子序列
System.out.println(m.start()+":"+m.end());//拿到位置。
}
}
//替换
public static void functionDemo_3() {
//叠词替换成"#"
// String str = "zhangsanttttlisimmmmmmmmmwangwu";
// str = str.replaceAll("(.)\\1+","#");
//多个叠词替换为一个字符:第二个参数想使用第一个参数正则中的内容, 可以用"$1":获取前一个参数中的第一组。
// String str = "zhangsanttttlisimmmmmmmmmwangwu";
// str = str.replaceAll("(.)\\1+","$1");
// System.out.println(str);
//号码隐藏
String tel = "15809673121";
tel = tel.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
System.out.println(tel);
}
//切割
public static void functionDemo_2() {
// String str = "zhangsan lisi wangwu";
// String[] names = str.split(" +");
// String str = "zhangsan.lisi.wangwu";
// String[] names = str.split("\\.");
String str = "zhangsanttttlisimmmmmmmmmwangwu";
//(.)第一个字符任意,后面的字符和前面一致,所以用()封装,并且自动编号,便于复用。
//称为组,"(.)\\1+"将数字转成组标号.不写().则默认为第0组
String[] names = str.split("(.)\\1+");
}
//匹配
public static void functionDemo_1(){
//匹配手机号码是否正确
String tel = "15832132342";
String regex = "1[358][0-9]{9}";//使用预定义字符时,反斜杠一律写两个,"\\d"
boolean b = tel.matches(regex);//使用String类中的matches();
System.out.println(tel+":"+b);
}
}</span>
四、练习
1.治疗口吃
2.对ip地址排序
3.对邮件地址校验
代码实现:
<span style="font-size:18px;">import java.util.TreeSet;
public class RegexTest {
public static void main(String[] args) {
/*
* 1.治疗口吃:我。。。我我。。。我我要。。。要要要要。。。要要学学。。。学学。。。学学学。。。编编编。。。编程程。。。程程。。。程程。。。程程
*
* 2.对ip地址排序
*
* 3.对邮件地址校验。
*
*/
// test_1();
// test_2();
test_3();
}
/*
* 3.对邮件地址校验。
*/
public static void test_3() {
String mail = "vsfe890@sina.com.cn";
//校验规则
String regex = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]{1,3})+";
// regex = "\\w+@\\w+(\\.\\w+)+";//1@1.1笼统匹配
boolean b = mail.matches(regex);
System.out.println(mail+":"+b);
}
/*
* IP地址排序
*
* 192.168.10.34 127.0.0.1 3.3.3.3 105.70.11.55
*
*/
public static void test_2(){
String ip_str = "192.168.10.34 127.0.0.1 3.3.3.3 105.70.11.55";
//为了让ip可以按照字符串顺序比较,只要让ip的每一段的位数相同。
//所以,要补零。按照每一位所需最多的0来补,即每一位补两个0.位数多的后面再舍弃。
ip_str = ip_str.replaceAll("(\\d+)", "00$1");
//然后每一段保留数字3位。
ip_str = ip_str.replaceAll("0*(\\d{3})", "$1");
TreeSet<String> ts = new TreeSet<String>();
//将ip地址切割
String[] ips = ip_str.split(" +");
for(String ip : ips){
// System.out.println(ip);
ts.add(ip);
}
for(String ip : ts){
System.out.println(ip.replaceAll("0*(\\d+)", "$1"));//输出时再替换
}
}
/*
* 治口吃
*/
public static void test_1(){
String str = "我...我我...我我要...要要要要......要要学学...学学...学学学...编编编...编程程...程程...程程...程程";
//1.将字符串中的"."替换成空字符。
str = str.replaceAll("\\.+", "");
// System.out.println(str);
//2.替换叠词
str = str.replaceAll("(.)\\1+", "$1");
System.out.println(str);
}
}
</span>
4.网页爬虫
这也是一个程序,在互联网中获取指定规则的数据。
下面以爬取邮箱地址为例:
<span style="font-size:18px;">public class RegexTest2 {
public static void main(String[] args) throws IOException {
List<String> list = getMailsByWeb();
for(String mail : list){
System.out.println(mail);
}
}
/*
* 爬取网页邮箱。跟本地爬取差不多,只是源改成了网上的。
*
*/
public static List<String> getMailsByWeb() throws IOException {
// //获取源文件
// BufferedReader bufr = new BufferedReader(new FileReader("mail.html"));
URL url = new URL("http:\\192.168.1.100:8080/myweb/mail.html");
BufferedReader bufr = new BufferedReader(new InputStreamReader(url.openStream()));
List<String> list = new ArrayList<String>();
//定义规则
String mail_regex = "\\w+@\\w+(\\.w+)+";
Pattern p = Pattern.compile(mail_regex);
//读取源文件并根据正则获取数据
String line = null;
while((line=bufr.readLine())!=null){
Matcher m = p.matcher(line);
while(m.find()){
//将符合规则的数据存储到list集合中
list.add(m.group());
}
}
return list;
}
public static List<String> getMails() throws IOException{
//获取源文件
BufferedReader bufr = new BufferedReader(new FileReader("mail.html"));
List<String> list = new ArrayList<String>();
//定义规则
String mail_regex = "\\w+@\\w+(\\.w+)+";
Pattern p = Pattern.compile(mail_regex);
//读取源文件并根据正则获取数据
String line = null;
while((line=bufr.readLine())!=null){
Matcher m = p.matcher(line);
while(m.find()){
//将符合规则的数据存储到list集合中
list.add(m.group());
}
}
return list;
}
}
</span>