18.正则表达式

时间:2022-12-15 16:55:51


 

一.正则表达式概述

        正则表达式用于操作字符串数据。通过一些特定的符号来体现的。所以我们为了掌握正则表达式,必须要学习一些符号。

       正则表达式虽然简化书写,但是阅读性差。所以开发时一般是将正则表达式封装到方法里,然后将要操作的字符串传递到方法里操作。

 

二. 正则表达式常用规则

1.字符类

 

符号

意义

[abc]

ab c(简单类)

[^abc]

任何字符,除了 ab c(否定)

[a-zA-Z]

a z A Z,两头的字母包括在内(范围)

[a-d[m-p]]

a d m p[a-dm-p](并集)

[a-z&&[def]]

de 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>