------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
正则表达式
1.什么叫做正则表达式?
正则表达式,又称正规表示法、常规表示法,计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。
很难理解吧?其实通俗讲就是符合一定规则的字符串表达式。
2.为什么我们要使用正则表达式?
当我们需要对字符串进行某些操作时,例如匹配,切割,替换,获取某一部分子串时,以前我们的做法是使用String类的方法,但是我们发现一个问题,如果需求比较简单还好,但是如果是比较复杂的需求呢?例如去验证一个字符串是否符合邮箱的格式,这时使用以前的方法就会写大量的代码,会使得程序结构看起来很复杂,冗长。这时我们需要一种新的解决问题的方法,那就是正则表达式。
例如:对于验证邮箱,我们只需要一下几步就可以解决问题,当然看不懂不要紧,后面我们详细讲解正则表达式的作用,现在我们先来见识一下它的威力吧。
String mail="helong4967@163.com.cn.cn";
String regex="[a-zA-Z0-9_]{4,10}@[a-zA-Z0-9_]+(\\.[a-zA-Z]+){1,3}";//这就是正则表达式
if(mail.matches(regex))
System.out.println("合法邮箱地址:"+mail);
else
System.out.println("不合法邮箱地址:"+mail);
我们可以看到,只需几行代码就可以解决原本很复杂的文本匹配工作。这就是正则表达式的威力。
正则的优势:相对于传统的调用String类的方法解决问题,这种解决方式更加简单便捷,极大的缩短了代码的长度。
正则的劣势:正是因为它将过多的规则放到一个字符串中,导致代码的阅读性有一定下降。
3.在正则表达式中有特殊含义的字符
字符类 | |
---|---|
[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](并集) |
[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](减去) |
预定义字符类 | |
---|---|
. | 任何字符(与行结束符可能匹配也可能不匹配) |
\d | 数字:[0-9] |
\D | 非数字: [^0-9] |
\s | 空白字符:[ \t\n\x0B\f\r] |
\S | 非空白字符:[^\s] |
\w | 单词字符:[a-zA-Z_0-9] |
\W | 非单词字符:[^\w] |
边界匹配器 | |
---|---|
^ | 行的开头 |
$ | 行的结尾 |
\b | 单词边界 |
\B | 非单词边界 |
\A | 输入的开头 |
\G | 上一个匹配的结尾 |
\Z | 输入的结尾,仅用于最后的结束符(如果有的话) |
\z | 输入的结尾 |
Greedy 数量词 | |
---|---|
X? | X,一次或一次也没有 |
X* | X,零次或多次 |
X+ | X,一次或多次 |
X{n} | X,恰好 n 次 |
X{n,} | X,至少 n 次 |
X{n,m} | X,至少 n 次,但是不超过 m 次 |
4.正则表达式的几个小知识点
组的概念:()用小括号包起来,编号从1开始,其他使用该组结果\1。例如匹配叠词(多个相同的字符):"(.)\\1+"
作用:让某部分规则的结果被重用。
组举例:((()())),编号就是按照左括号以此排列(1(2(3)(4)))
作用:让某部分规则的结果被重用。
组举例:((()())),编号就是按照左括号以此排列(1(2(3)(4)))
5.对字符串使用正则表达式的几个基本操作
1.匹配(只想知道是对是错):
String.matches(regex)。
2.切割(获取到按照规则分开的所有串):
String.split(regex)。
3.替换(想用某一个新串代替原来中一部分):
String.replaceAll(regex,str)。非法字符打码。使用str替换字符串中regex匹配部分。
4.*获取(拿到想要的符合规则的子串):
涉及到两个对象:Pattern,Matcher。
String.matches(regex)。
2.切割(获取到按照规则分开的所有串):
String.split(regex)。
3.替换(想用某一个新串代替原来中一部分):
String.replaceAll(regex,str)。非法字符打码。使用str替换字符串中regex匹配部分。
4.*获取(拿到想要的符合规则的子串):
涉及到两个对象:Pattern,Matcher。
Pattren类常用方法:compile。
Matcher类常用方法:matches,find,group,start,end。
取到符合规则的子串。
基本思路步骤:
1.将正则封装成对象。Pattern类。
2.将该对象与字符串对象相关联。Pattern的matcher方法。
3.关联后,获取正则对象的匹配引擎。matcher的返回值为引擎。
4.通过该引擎,对匹配的子串进行操作,例如获取。
其实String类中的matches方法用的就是Pattern和Matcher完成的。
5网页爬虫(蜘蛛):
使用程序对网页进行内容检索,例如获取其中所有的邮箱等等。
1.先获取其网页内容。
2.对内容进行正则匹配邮箱。
3.将邮箱保存下来。
取到符合规则的子串。
基本思路步骤:
1.将正则封装成对象。Pattern类。
2.将该对象与字符串对象相关联。Pattern的matcher方法。
3.关联后,获取正则对象的匹配引擎。matcher的返回值为引擎。
4.通过该引擎,对匹配的子串进行操作,例如获取。
其实String类中的matches方法用的就是Pattern和Matcher完成的。
5网页爬虫(蜘蛛):
使用程序对网页进行内容检索,例如获取其中所有的邮箱等等。
1.先获取其网页内容。
2.对内容进行正则匹配邮箱。
3.将邮箱保存下来。
6.正则小练习
/*
QQ:5-15位,全数字,0不能开头
练习:
匹配手机号
切割
替换
*/
class RegexDemo
{
public static void main(String[] args)
{
checkQQ_1();
checkQQ_2();
checkTel();
split();
replaceAll();
}
private static void checkQQ_1()
{
String QQ="01232345";
if((QQ.length()<=15 && QQ.length()>=5) && !(QQ.startsWith("0")))
{
//方法1:
/*
char[] buf = QQ.toCharArray();
boolean flag = true;
for(int i=0;i<buf.length;i++)
{
if(!(buf[i]>='0' && buf[i]<='9'))
{
flag=false;
break;
}
}
*/
//方法2:
boolean flag = true;
try
{
long qq=Long.parseLong(QQ);
}
catch (Exception e)
{
flag=false;
}
if(flag)System.out.println("QQ号合法");
else
System.out.println("QQ号不合法");
}
else
{
System.out.println("QQ号不合法");
}
}
private static void checkQQ_2()
{
String QQ="33aa25";
String regex="[1-9][0-9]{4,14}";
boolean flag=QQ.matches(regex);
if(flag)
System.out.println("QQ号合法:"+QQ);
else
System.out.println("QQ号不合法:"+QQ);
}
private static void checkTel()
{
//号段只有:"13xxx,15xxx,18xxx"
String tel="13977139736";
String regexTel="[1][358]\\d{9}";
if(tel.matches(regexTel))
System.out.println("合法电话号码:"+tel);
else
System.out.println("不合法电话号码:"+tel);
}
private static void split()
{
String data="adfwwdfadgwetgddsdafsssdfweee";
String regex="(.)\\1";
String[] strs=data.split(regex);
for(String str : strs)
{
System.out.println(str);
}
}
private static void replaceAll()
{
String data="adfwwdfadgwetgddsdafsssdfweee";
//屏蔽叠词,用#替换
//String regex="(.)\\1+";
//data=data.replaceAll(regex,"#");
//System.out.println(data);
//将叠词变成单个字符zzzz->z
String regex="(.)\\1+";
//$1表示的是前一个表达式的第一组的结果
data=data.replaceAll(regex,"$1");
System.out.println(data);
}
}
运行图:
//练习:获取
/*
获取步骤:
1.将正则封装成对象Pattern(模式)
2.将该对象与操作字符串相关联Pattern.matcher(str)相关联
3.获取匹配引擎。第二部的返回值为引擎。
4.通过该引擎对字符串进行某些操作,例如获取。
*/
import java.util.regex.*;
class RegexDemo2
{
public static void main(String[] args)
{
Pattern p = Pattern.compile("\\b[a-zA-Z]{3}\\b");
Matcher m = p.matcher("wos men ai ni zhong guo , qin ai de mu qin .");
System.out.println("wos men ai ni zhong guo , qin ai de mu qin .");
//matches,find,group,start,end,reset
//注意一点:同一个匹配器,它的所有方法使用的是同一个索引,因此当一个方法使得
//索引位移动时,其他方法也将使用移动后的索引位。
System.out.println("matches():"+m.matches());
//利用以下两个方法可以做到将字符串中符合规则的子串全部取出的操作
System.out.println("find():"+m.find());
System.out.println("group():"+m.group());
System.out.println("start():"+m.start()+"....end():"+m.end());
m.reset();
while(m.find())
{
System.out.println(m.group()+"..."+m.start()+","+m.end());
}
}
}
运行图:
import java.util.*;
class RegexTest
{
public static void main(String[] args)
{
check1();
check2();
check3();
}
private static void check1()
{
//问题1
/*
将下列字符串
"我我..我我..我要...要要..要要.....要学....学学...学编.....编编....编程....程程"
变成
"我要学编程"
*/
String str="我我..我我..我要...要要..要要.....要学....学学...学编.....编编....编程....程程";
String regex="";
str=str.replaceAll("\\.","");
str=str.replaceAll("(.)\\1++","$1");
System.out.println(str);
}
private static void check2()
{
//重点:理解正则的用法
//问题2
/*
需求:将ip地址排序。
思路:
1.先都补两个0,保证至少有三位
2.将多余三位的保留后三位
3.排序
4.打印的时候将前面的0去掉,例如002变成2
*/
String ip="192.168.0.1 101.20.20.3 2.2.2.2 8.8.7.6 192.111.101.202";
ip=ip.replaceAll("([0-9]+)","00$1");
System.out.println(ip);
ip=ip.replaceAll("0*([0-9]{3})","$1");
System.out.println(ip);
String[] ips=ip.split(" +");
Arrays.sort(ips);
for(String str : ips)
{
System.out.println(str.replaceAll("0*([0-9]+)","$1"));
}
}
private static void check3()
{
//问题3
/*
需求:对邮件地址进行校验
*/
String mail="helong4967@163.com.cn.cn";
String regex="[a-zA-Z0-9_]{4,10}@[a-zA-Z0-9_]+(\\.[a-zA-Z]+){1,3}";
if(mail.matches(regex))
System.out.println("合法邮箱地址:"+mail);
else
System.out.println("不合法邮箱地址:"+mail);
}
}
运行图:
7.正则总结及心得
通过使用正则表达式,我们发现它的威力确实非常大,能将非常复杂的逻辑检索工作变得只用简单的一两行代码来解决,当然,前提是能够熟练的掌握正则表达式,这需要大量的练习,我相信不管到了什么时候,正则都会是处理文本的一把利剑。
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------