什么是正则表达式:
符合一定规则的表达式
作用:用于专门操作字符串
特点:用一些特定的符号来表示一些代码操作,这样就简化书写
所以学习正则表达式,就是在学习一些特殊符号的使用
好处:可以简化对字符串的复杂操作
弊端:符号定义越多,正则越长,阅读性越差。
具体操作功能:
1,匹配:String matches方法 用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false
2,切割:String split( String regex)
3,替换:String replaceAll(String regex,String newStr);
例如:输入一个字符串类型的QQ号码,要求号码在4-15位,0不能开头,必须全部都是数字。
按照之前的方法我们是这样做的:
//对字符串式的扣扣号进行判断,
//扣扣号一共有4~15位
//0不可以作为开头
//只能是数字
public class CheckQQDemo {
public static void main(String[] args)
{
String qq = "0123454747689";
checkQQ(qq);
}
//该方法传进来一个字符串类型的数据,先判断字符串的长度是否符合规则
//如果符合上一条,判断是不是以0开头的
//如果不是,则将字符串全部转换成long类型的数,如果转换成功,说明数据合法
//如果没有转换成功,会抛出异常,输出该数据不合法
public static void checkQQ(String qq)
{
if(qq.length()<16 && qq.length()>3)
{
if(!qq.startsWith("0"))
{
try
{
long l = Long.parseLong(qq);
System.out.println(l+"是正确的");
}
catch (Exception e)
{
System.out.println(qq+"是不正确的");
}
}
else
{
System.out.println("0不可以作为开头");
}
}
else
{
System.out.println("字数不符合规定");
}
}
}
运行结果:
而当我们用正则表达式进行校验的时候,就简单多了;
//使用正则表达式判断qq号是否合法
//还是按照之前的规则
public class CheckQQDemo2 {
public static void main(String[] args)
{
String qq = "0123456789";
checkQQ(qq);
}
public static void checkQQ(String qq)
{
//定义正则表达式,表示第一位是从1-9的数,后边的数据范围从0-9,这样的数据一共有3-14位
String regex = "[1-9][0-9]{3,14}";
//拿指定的字符串和正则表达式进行比较,符合写的正则表达式,就返回真
boolean b = qq.matches(regex);
if(b)
System.out.println(qq+"是合法的");
else
System.out.println(qq+"是不合法的");
}
}
运行结果:
正则表达式中有自己的表示字符的方法:
比如:
还有自己特定的表达数量的操作:
有了这样之后,我们来检测一下手机号码;
手机号码是这样的,第一位必须是1,第二位是3,5,8,后边的数字就随便了,,手机号长度是11位:
代码如下:
//检测手机号是否符合规则
public class CheckTel {
public static void main(String[] args)
{
String s1 = "18654652312";
String s2 = "25465854569";
String s3 = "14523652156";
String s4 = "4563";
checkTel(s1);
checkTel(s2);
checkTel(s3);
checkTel(s4);
}
public static void checkTel(String s)
{
String regex = "[1][358]\\d{9}";//第一位是1,第二位是358中间的一个,后边的是9位0-9的数字
//拿正则表达式匹配传进来的数据
boolean b = s.matches(regex);
if(b)
{
System.out.println(s+"是规则正确的手机号");
}
else
{
System.out.println(s+"是不合规则的手机号");
}
}
}
运行结果:
用正则表达式切割字符串:
//用正则表达式切割字符串
public class SplitDemo {
public static void main(String[] args)
{
splitDemo("zhangsan,lisi,wangwu",",");//使用,切割
//splitDemo("zhangsan.lisi.wangwu",".")
//因为在正则表达式中,.表示的是任意字符,所以需要加\转义,表示他是一个.
//而正则表达式定义在字符串中,字符串会把\.再进行转义,所以需要再加一个\
splitDemo("zhaoliu.zhouqi.sunba","\\.");
//按照叠词切割,就是说碰到像aa,bb,cc这样的,就开始切割
splitDemo("hkddsaffhdsaaf","(.)\\1");//分组:当读到一个字符的时候,将这个字符装在一个组里边,
//这个组是第一个组,所以标号为1,
//当遇到的第二个字符和前一个字符一样时,就开始切割
//正则表达式中前一个表示任意字符,后一个表示前一个字符
//如果叠词有多个呢?比如想要在aaa,bbbb这样的地方也需要切割呢?简单,正则后边加个+就可以了(一个或多个)
splitDemo("fjjjdksaaaaaljaklllllljgk","(.)\\1+");
}
public static void splitDemo(String s,String regex)
{
String[] strs = s.split(regex);
System.out.print(s+": "+"使用 "+regex+" 切割为");
for(String s1:strs)
{
System.out.print(s1+" ");
}
System.out.println();
}
}
运行结果:
替换:将字符串中符合规则的子串替换成指定的字符(串)
//替换演示,将符合指定规则的字符串替换成指定字符
public class ReplaceAllDemo {
public static void main(String[] args)
{
//把全部的数字变成#
replaceAllDemo("fdfd4545dagd445fdfd878","\\d+","#");//将喷到的一个或多个数字变成#
//将叠词替换成&
replaceAllDemo("jdeeeafdjkkkksalnnnvae","(.)\\1+","&");//将碰到的一个或多个叠词,换成符号&
//将叠词替换成单个的字符
replaceAllDemo("jfffdsssjgaaadsjjjs","(.)\\1+","$1");//将碰到的叠词转换成单个字符
//$1可以表示在正则表达式中的组里边的元素
//也就是(.)
}
public static void replaceAllDemo(String s,String regex,String newStr)
{
s = s.replaceAll(regex,newStr);
System.out.println(s);
}
}
运行结果:
正则表达式的第四个功能。
4,获取:将字符串中的符合规则的子串取出。
操作步骤:
1,将正则表达式分装成对象
2,让正则对象和要操作的字符串相关联
3,关联后,获取正则匹配引擎
4,通过引擎对符合规则的子串进行操作,比如取出。
//获取字符串中符合规则的子串
//将整串字符串中的三个字母的单词提取出来
import java.util.regex.*;
public class GetDemo {
public static void main(String[] args)
{
String str = "ming tian jiu yao fang jia le , haha";
//正则表达式,两边是单词边界
String regex = "\\b[a-z]{3}\\b";
getDemo(str,regex);
}
public static void getDemo(String str,String regex)
{
//将正则表达式封装成对象
Pattern p = Pattern.compile(regex);//将给定的正则表达式编译到模式中
//建立正则对象和字符串的匹配对象
Matcher m = p.matcher(str);
//找到符合正则表达式的字符,并且打印出来
while(m.find())//对符合条件的子串进行查找
{
System.out.println(m.group());//获取匹配后的结果
}
}
}
运行结果:
在Matcher对象中,也可以使用matches方法,和String类中的方法是一样的,
String类中的的matches方法用的就是Pattern和Matcher对象来完成的,
只不过被String的方法封装后,用起来较为简单,但是功能却单一了。
练习:将一个下列字符串变成“我要学编程”
“我…我我…我我…我…要.要.要…要…要…要…学学…学…学…学编编…编…编程…程…程…程”
public class RegexTest1 {
public static void main(String[] args)
{
String s = "我...我我.....我我....我...要.要.要...要.....要....要......学学....学...学..学编编...编...编程....程.....程...程";
/*
思路:先把所有点点去掉,用的是替换,将多个.替换成""空字符串
再判断重叠词,替换成一个字就可以了
*/
s = s.replaceAll("\\.+","");
s = s.replaceAll("(.)\\1+","$1");
System.out.println(s);
}
}
运行结果:
练习2 :给列出的IP地址按照网段排序:
import java.util.*;
public class RegexTest2 {
public static void main(String[] args)
{
String ip = "192.168.0.1 2.2.2.2 10.56.42.7 202.207.232.10";
//考虑一种情况,开头为10和开头为2的IP地址比较的话,10会排在前边,
//这不行,想要按照网段排序,现在前边补0
ip = ip.replaceAll("(\\d+)","00$1");//取到一个或多个数字,替换成前边加两个0的
//System.out.println(ip);
//然后判断后边三个数之前有0的,将0替换掉
ip = ip.replaceAll("0*(\\d{3})","$1");//前边有0或者没0的,后边保留三位数
//System.out.println(ip);
//将IP地址按空格分离开,存进集合中,让集合给排序
String[] strs = ip.split(" ");
TreeSet<String> set= new TreeSet<String>();
for(String s:strs)
{
set.add(s);
}
for (String s:set)
{
System.out.println(s);
}
}
}
运行结果:
练习三:对一个邮箱进行验证:
public class RegexDemo3 {
public static void main(String[] args)
{
String mail = "123abc@sina.com.cn";
//开始定义正则表达式
String regex = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}";
//开始匹配
boolean b = mail.matches(regex);
System.out.println(b);
}
}
网页爬虫/蜘蛛
他想往邮箱里边发广告,那么就想获取到其他资源中的已经注册过的邮件
于是就在网络上按照正则表达式读取网络上的数据,将符合邮箱规则的数据读取出来
然后往里边发广告,
现在我们先用读取一个文件中的邮箱信息:
import java.io.*;
import java.util.regex.*;
public class GetMailTest {
public static void main(String[] args) throws Exception
{
String mailRegex = "\\w+@\\w+(\\.\\w+)+";
//将正则封装成对象
Pattern p = Pattern.compile(mailRegex);
//开始读取文件中的数据
BufferedReader bufr = new BufferedReader(new FileReader("mail.txt"));
String line = null;
while((line = bufr.readLine())!=null)
{
//每读取一次数据,就建立一次正则对象和字符串的连接
Matcher m = p.matcher(line);
//然后开始读取有没有符合正则对象的数据
while(m.find())
{
//有的话就获取符合规则的数据
System.out.println(m.group());
}
}
}
}
运行结果:
那么可不可以从网页上获取邮件资源呢?
现有如下网页:里面包含了各种邮箱
那么就考虑获取到网页上的对象:
之前学过的URL对象就可以用的上了::
//获取网页中的邮箱资源
import java.io.*;
import java.util.regex.*;
import java.net.*;
public class GetMailTest2 {
public static void main(String[] args) throws Exception
{
//将网页路径封装成URL对象
URL url = new URL("http://127.0.0.1:8080/myweb/mail.html");
URLConnection conn = url.openConnection();//通过对象获取到远程连接对象
BufferedReader bufr = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
String regex = "\\w+@\\w+(\\.\\w+)+";
Pattern p = Pattern.compile(regex);
while((line = bufr.readLine())!=null)
{
Matcher m = p.matcher(line);
while(m.find())
{
System.out.println(m.group());
}
}
}
}
运行结果:
结果显示,可以获取到数据。