------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------
正则表达式
在生活中,我们需要对数据进行处理,比如需要对数据进行校验,匹配,切割,替换等操作,但是有的人会说,我们可以使用String的功能对数据进行处理,但是我们知道,String类只能处理一些功能比较简单的操作,如果要处理比较复杂的逻辑,还要写很复杂的代码,接下来我们介绍正则表达式,正则表达式的原理:就是具有一定规则的表达式,主要对字符串进行操作。
正则表达式用于匹配
演示实例代码如下:
/*正则表达式主要具有一定规则的表达式
*主要是对字符串进行操作
*生活实例:qq的长度必须在5-15位,只能为数字,不能以0开头
*/
代码如下:
class RegesDemo1_1
{
public static void main(String[] args)
{
regesCkeck();
regesCheck2();
}
public static void regesCkeck()
{
String reges="[1-9][0-9]{4,14}";//定义正则表达式(第一位不能为0,后面的必须是数字并且出现的此时4次到14次)
String qq="12a343DDD98";
if(qq.matches(reges))
{
System.out.println(qq);
}
else
{
System.out.println("qq号非法");
}
}
public static void regesCheck2()
{
String text="ab";
String reg1="[abc][cdefg]";
String reg2="[abc][^cdefg]";
String reg3="\\d";
System.out.println(text.matches(reg1));
System.out.println(text.matches(reg2));
//第一位是字母,第二位有可能有数字,有可能没有数字
String text1="a1";
String reg4="[a-zA-Z][0-9]?";//要么一次,要么一次也没有。
System.out.println(text1.matches(reg4));
//校验电话号码
//电话号码要么是13******,或者是15**********或者是18***********
//代码如下:
String num="13543554763";
String numreg="1[358]\\d{9}";
System.out.println(num.matches(numreg));
}
}
/*
[abc] 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](并集)
. 任何字符(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
*/
正则表达式用于切割:
正则表达式还可以对字符串进行一定的复杂规则的切割,我们可以定义正则表达式的规则
class RegesDemo1_2
{
public static void main(String[] args)
{
regFunction1();
regFunction2();
regFunction3();
regFunction4();
}
public static void regFunction1()
{
String str="zhangsan li wangwu";
String reg=" +";//主要用于切割字符串中有一个或者多个空格的情况
String[] arr=str.split(reg);
for(String s :arr)
{
sop(s);
}
}
public static void regFunction2()
{
String str="zhangsan.li.wangwu";
String reg="\\.";//.在正则表达式中表示任意字符,所以如果需要使用.这个符号进行切割,所以就必须使用\进行转义,所以\.表示正则表达式中的.但是这个\.中又在字符串中,如果直接写成\.则又会进行转义,所以必须再加一个\来表示正则表达式中.
String[] arr=str.split(reg);
for(String s :arr)
{
sop(s);
}
}
public static void regFunction3()
{
String str="c:\\demo\\a.text";//按照\\进行切割,所以正则表达式应为\\\\
String reg="\\\\";//
String[] arr=str.split(reg);
for(String s :arr)
{
sop(s);
}
}
public static void regFunction4()
{
//如果叠词出现的次数不固定的话
String str="ckkdeemooatext";//按照叠词进行切割,比如该字符串中存在kk ee oo这样的字符,
String reg="([a-zA-Z])\\1+";//为了让定义的规则能够被重复的使用,可以将需要重复的结果进行分组,使用()来完成,而且每个组都有资金的编号。组的编号从一开始,可以使用\n来获取已有的组,n表示组的编号。
String[] arr=str.split(reg);
for(String s :arr)
{
sop(s);
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果如下:
接下来我们来讨论如何使用正则表达式按照指定的规则来替换字符串。
字符串的功能中有一个replaceAll(String regex,String replacement)
使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符的
所以根据这个方法我们可以给字符串转入指定的正则表达式格式
演示代码如下:
class RegesDemo1_3
{
public static void main(String[] args)
{
replaceDemo1();
replaceDemo2();
replaceDemo3();
}
public static void replaceDemo1()
{
String str1="aglgdakf1111W432";//使用#替换字符串中的数字,
String reg="\\d+";
String s=str1.replaceAll(reg,"#");
sop(s);
}
public static void replaceDemo2()
{
String str1="aglllgddakkf";//将叠词替换成#号
String reg="(.)\\1+";
String s=str1.replaceAll(reg,"#");
sop(s);
}
public static void replaceDemo3()
{
String str1="aglllgddakkf";//将叠词替换成单个字符,比如kkk替换成k,rr替换成r,替换的字符串和组的符号是相同的,我们可以用$n来获取组的内容,n为组的编号
String reg="(.)\\1+";
String s=str1.replaceAll(reg,"$1");
sop(s);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
前面我们介绍的正则表达式比如匹配是返回boolean值,切割也是按照正则表达式的规则进行切割,并不包含正则表达式本身,另外替换页是将原字符串按照规则替换成新的字符串,接下来我们将利用正则表达式获取符合规则的子字符串从原字符串中取出。
操作步骤如下:
1将正则表达式封装成对象
2将正则表达式对象和需要操作的字符串进行关联
3关联后,获取匹配引擎
4通过引擎对符合规则的字串进行操作,比如取出。
代码如下:
import java.util.regex.*;
class RegesDemo1_4
{
public static void main(String[] args)
{
regesFun();
regesFun2();
}
//校验qq号的实例,第一位不能为0,后面全部为数字,长度一共为5位或者15位。
public static void regesFun()
{
String reg="[1-9]\\d{4,14}";
String num="131244";
//1将正则表达式封装成对象
Pattern p=Pattern.compile(reg);
//2将正则对象和要进行操作的字符串进行关联;
//获取正则表达式匹配引起
Matcher a=p.matcher(num);
System.out.println(a.matches());
}
//需求:找出字符串中字母个数为3个的单词
public static void regesFun2()
{
String str="ming tian yao fang jia le ,tong xue";
String reg="\\b[a-zA-Z]{3}\\b";//注意着在边界匹配器中有一个单词的匹配器\b用它可以来表示单词。
Pattern p=Pattern.compile(reg);
Matcher m=p.matcher(str);
while(m.find())//find()尝试查找与该模式匹配的输入序列的下一个子序列。
{
System.out.println(m.group());
// 返回在以前匹配操作期间由给定组捕获的输入子序列。
System.out.println(m.start()+"……"+m.end());
//返回符合条件的子串在原串中的起始索引,和结尾索引
}
//在同一个封装的正则对象作用的是同一个指针。
}
}
正则表达式为我们提供了对字符串操作的很方便的功能。
那我们该怎么使用这些功能呢??应该在什么时候使用这些功能呢??
*正则表达式的操作规则:
*1如果需要判断字符串是否符合某个规则,那么就使用正则表达式的匹配功能
*2如果要将原字符串变成另一个字符串,那么就使用正则表达式的替换功能
*3如果要将字符串变成多个字符串,就可以使用字符串的切割功能,不包含符合规则的
4如果想要获取符合某个规则的字串,那么就可以使用正则表达式的获取功能。
*/
演示代码如下:
class RegesDemo1_5
{
public static void main(String[] args)
{
regeFun();
}
//需求:
//将下面的字符串变成 我要学编程这几个字
//分析:这里主要是使用正则表达式的替换功能
public static void regeFun()
{
String str = "我我...我我...我要..要要...要要...学学学....学学...编编编...编程..程.程程...程...程";
//1去掉.号
String reg="\\.+";
String temStr=str.replaceAll(reg,"");
System.out.println(temStr);
//2去掉叠词
String reg1="(.)\\1+";
String temStr1=temStr.replaceAll(reg1,"$1");
System.out.println(temStr1);
}
}
演示代码二:
代码如下:
import java.util.*;
class RegesDemo1_6
{
public static void main(String[] args)
{
RegFun();
}
/*
*192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30这个字符串中存在多个ip地址,现在我们需要对这些ip地址进行排序,排序的规则是按照网段进行大小排序,但是通过观察我们发现每个网段的ip地址的长度都不相同,所以这时就需要我们先将这些地址进行补齐到相同的位数,然后再进行比较
*
*/
public static void RegFun()
{
String ip="192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30";
//将每个网段的数字都补齐2个零。
String reg1="(\\d+)";
String str1=ip.replaceAll(reg1,"00$1");
//str1="00192.0068.001.00254 00102.0049.0023.00013 0010.0010.0010.0010 002.002.002.002 008.00109.0090.0030"
System.out.println(str1);
//然后去将每一位都只保留三位有效的数字,(去掉补多的零);
String reg2="0*(\\d{3})";
String str2=str1.replaceAll(reg2,"$1");
System.out.println(str2);
//str2="192.068.001.254 102.049.023.013 010.010.010.010 002.002.002.002 008.109.090.030"
//按照空格将字符串切成包含ip的数组
String[] arr=str2.split(" +");
//然后对数组中ip地址按照网段进行排序;
TreeSet<String> ts=new TreeSet<String>();
for(String s:arr)
{
ts.add(s);
}
//使用TreeSet进行排序,并输出结果。
for(String s: ts)
{
System.out.println(s.replaceAll("0*(\\d+)","$1"));
}
}
}
演示实例三:
需求:校验邮箱
代码如下:
/*校验邮箱*/
class RegesDemo1_7
{
public static void main(String[] args)
{
regesFun();
}
public static void regesFun()
{
//email地址:aaabbdfas_33@sina.com
//dfasdfafds_43@sina.com.cn;
String email="aaabacd33_@163.com.cn";
String reges="[a-zA-Z0-9_]{5,10}@[a-zA-Z0-9]+(\\.[a-z]{2,3})+";
System.out.println(email.matches(reges));
}
}
在生活中,我们为了获取一些文件中(普通文件,html文件,其他文件等)符合我们定义的规则的信息,并且编写一个小程序从服务端取回来为我们自己用,向这样的小程序就叫做网页爬虫
接下来我们来演示网络爬虫的具体实例,代码如下:
import java.util.*;
import java.util.regex.*;
import java.io.*;
import java.net.*;
class RegesDemo1_8
{
public static void main(String[] args) throws Exception
{
//pachong1();
pachong2();
}
//从本地文件中爬取我们想要的信息(比如说邮箱地址)
public static void pachong1()throws Exception
{
BufferedReader bw=
new BufferedReader(new FileReader("mail.txt"));
String line=null;
String mailReg="\\w+@\\w+(\\.\\w{1,3})+";//邮箱的正则表达式
Pattern p=Pattern.compile(mailReg);
while((line=bw.readLine())!=null)
{
Matcher m=p.matcher(line);//让需要操作的字符串和正则对象进行关联
while(m.find())
{
System.out.println(m.group());
}
}
}
//从服务端获取数据,并采用网络爬虫技术,获取有用的信息
public static void pachong2()throws Exception
{
URL url=new URL("http://127.0.0.1:8090/mail.html");
URLConnection conn=url.openConnection();
BufferedReader br=
new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line=null;
String mailReg="\\w+@\\w{1,5}(\\.\\w{1,3})+";
Pattern p=Pattern.compile(mailReg);
while((line=br.readLine())!=null)
{
Matcher m=p.matcher(line);
while(m.find())
{
System.out.println(m.group());
}
}
}
}