您的位置:首页 > 职场人生

黑马程序员--正则表达式

2015-04-01 17:00 405 查看
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

正则表达式:符合一定规则的表达式。

作用:专门用于操作字符串。
特点:用一些特定的符号来表示一些代码操作。这样就简化书写。
好处:可以简化对字符串的复杂操作。
所以学习正则表达式,就是在学习一些符号的使用
弊端:符号定义越多,正则越长,阅读性越差


String 类中提供的方法较简单,组合起来操作代码麻烦,

正则表达式是对字符串即便捷又简单的操作方法。

下面通过一个小例子来体现以下正则表达式。

/*
需求:
对QQ号码进行校验,要求5-15位,0不能开头,只能是数字
*/
class CheckQQDemo
{
public static void main(String[] args)
{
//method_1("1254444454635555");
method("23434d5555");
}

//使用正则表达式
public static void method_1(String qq)
{
String regex="[1-9][0-9]{4,14}";
boolean flag=qq.matches(regex);
if(flag)
System.out.println(qq+"..is ok");
else
System.out.println(qq+".....no OK");
}

//不使用正则表达式
//这种方式使用了String类中的方法进行组合完成需求,但是代码过于复杂
public static void method(String qq){
int len=qq.length();
if(len>=5&&len<=15)
{
if (!qq.startsWith("0"))
{
try
{
long l=Long.parseLong(qq);
System.out.println("qq:"+qq);
}
catch (NumberFormatException e)
{
System.out.println("出现非法字符");
}

/*
char[] arr=qq.toCharArray();
boolean flag=false;
for (int i=0; i<arr.length; i++)
{
if(!(arr[i]>'0'&&arr[i]<='9'))
{
flag=true;
break;
}
}
if(!flag)
{
System.out.println("qq:"+qq);
}
else
{
System.out.println("出现非法字符");
}
*/
}
else
{
System.out.println("不可以0开头!");
}
}
else
{
System.out.println("长度错误");
}
}
}


通过上面的示例可以看出正则表达式,极大地简化了书写,让操作变得很方便。

正则表达式中常用的一些特殊符号:

字符类符号

[abc]可以判断一个字符串当中某一个字符位上出现的字符,a或b或c
eg:a.matcheds("[bcd]"); 返回的是false。
[a-zA-Z]
[^abc]
[a-d[m-p]]a到d或m到p去交集
预定义字符:
.    任意字符
\d   任意数字 使用时 \\d
注意在正则表达式中\\总是成对出现
\D   任意非数字
\s   空白字符[\t\n\0B\f\r]
\S   非空白字符
\w   单词字符[a-zA-Z_0-9]  邮箱校验
\W   非单词字符
数量词:
X?       X,一次或一次也没有
X*       X,零次或多次
X+       X,一次或多次
X{n}     X,恰好 n 次
X{n,}    X,至少 n 次
X{n,m}   X,至少 n 次,但是不超过 m 次
边界匹配器
^ 行的开头
$ 行的结尾
\b 单词边界
\B 非单词边界
\A 输入的开头
\G 上一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符(如果有的话)
\z 输入的结尾


正则表达式对字符串的具体操作:

1.匹配

boolean matches()方法。用规则匹配整个字符串,只要有一处不符合,就返回false

eg:

QQ匹配:[1-9]\d{4-14}

匹配手机号码:

要求:手机号段只有13***,15***,18***

手机号码匹配正则:1[358]\d{9}

2.切割

String[] split(String regex)

public static void splitDemo()
{
/*
String str="zhangsan   lisi     wangwu zhaoliu    heh";
String reg=" +";//按照多个空格进行切割
*/
/*
String str="zhangsan.lisi.wangwu.zhaoliu.heh";
//String reg=".";//.是正则表达式中的符号,直接用.切出错
//想使用.必须先将.转义,给.转义的\也是正则表达式中的符号,所以需要把\也转义,即\\.
String reg="\\.";
*/
/*
String str="C:\\abc\\a.txt";
String reg="\\\\";//很特殊的部分,使用时一定要小心
*/
//按照叠词切
String str="erkkbfdffdkkd";
String reg="(.)\\1";
String[] arr=str.split(reg);
for (String s: arr)
{
System.out.println(s);
}
}


按照叠词切String str=”erkkbfdffdkkd”;

String regex=”“;

该怎么切呢?

这就涉及到了组的概念。
把要重用的部分用(.)括起来,通过\n的形式来捕获组"(.)\\1"
重用的部分超过2次"(.)\\1+"
为了让规则的结果被重用可以将规则封装成一个组。用()完成。
组的出现都有编号,从1开始。想要使用已有的组可以通过\n(n就是组的编号)的形式来获取

((())())   看有几组可以数()的个数,有几个()就有几组
组的出现就体现出来了正则表达式的弊端:阅读性极差


3.替换

replaceAll(String regex,String replacement)

public static void replaceAllDemo()
{
//模拟发帖子中带有qq账号信息,将带有的qq信息替换成#
/*
String str="wer1235555dd488488494654dfdfdg";
String reg="\\d{5,}";
str=str.replaceAll(reg,"#");
*/
/*
//将叠词替换成&
String str="erkkbfdffdkkkkkkd";
String reg="(.)\\1+";
str=str.replaceAll(reg,"&");
*/
//将叠词替换成单个字符kk-->k   zzzz-->z
String str="erkkbfzzzzdffdkkkkkkd";
String reg="(.)\\1+";
//★★★特殊
str=str.replaceAll(reg,"$1");//可以通过$获取前一个规则中的组
System.out.println(str);
}
}


4.获取 按照规则把符合规则的子串取出

操作步骤:

1.将正则表达式封装成对象
2.让正则对象和要操作的字符串相关联
3.关联后,获取正则匹配引擎
4.通过引擎对符合规则的子串进行操作,比如取出


与获取操作有关的类:

Pattern 该类无构造函数,根据经验该类会提供静态方法返回本类对象。

Pattern.compile(String regex);

Matcher 很吊的一个类,里面提供了各种方法

import java.util.regex.*;
class RegexDemo
{
public static void main(String[] args)
{
getDemo();
}

public static void getDemo()
{
//需求将字符串中连续三个字母的子串取出    eg:取出jiu  yao  jia
String str="ming tian jiu yao fang jia le";

//String regex="\\w{4}";//单词有边界,这里需要使用单词边界匹配

String regex="\\b\\w{4}\\b";
//1.将规则封装成对象
Pattern p=Pattern.compile(regex);

//2.让正则对象和要操作的字符串相关联。获取匹配器对象。
Matcher m=p.matcher(str);
/*
学习到这里可以看出,String类中的matcher方法用的就是
Pattern和Matcher中的matcher方法,只不过是String类把
这些方法封装在了内部,用起来较为简单,但是功能单一,
想要使用更多复杂功能,就要回来找Pattern和Matcher类。
*/
/*
boolean b=m.find();//将规则作用到字符串上,并进行复核规则的子串查找

System.out.println(b);

System.out.println(m.group());//获取匹配结果
*/

//System.out.println(m.matches());
//一个小细节:如果下面的代码前面加上上面的这句m.matches(),
//则输出结果会有可能发生错误,ming没有输出,这是因为一个匹
//配引擎内部使用的是同一个角标,而matches()方法作用于整个字
//符串,当匹配结束返回false,角标已经到了tian的t的位置,因
//此,调用find()方法,角标是从t的位置开始的,结果中就少了个ming。
//使用时一定要注意。
while(m.find())
{
System.out.println(m.group());
}
}
}


正则表达式解决问题比较通用的思考方式:

1.如果只想知道该字符串是对是错,匹配。
2.想要将已有的变为另一个字符串,替换。
3.想要按照自定的方式将字符串变成多个字符串,切割。获取规则以外的子串
4.想要拿到符合需求的字符串子串,获取。 获取符合规则的子串


两个关于正则的小练习:

import java.util.*;
class RegexTest
{
public static void main(String[] args)
{
//ipSort();
checkMail();
}
/*
练习:将ip地址按照ip地址段顺序排序
192.168.1.254 102.49.23.013 10.10.10.10 2.2.2.88 8.109.55.90
升序排序
思路:
还按照字符串自然顺序排列,只要让他们每一段三位即可
1.按照每一段需要的最多的0进行补齐,那么每一段就会至少保证三位。
2.将每一段只保留3位,这样,所有ip地址都是每一段三位
*/
public static void ipSort()
{
String ip="192.168.1.254 102.49.23.013 10.10.10.10 2.2.2.88 8.109.55.90";
ip=ip.replaceAll("(\\d+)","00$1");
System.out.println(ip);
ip=ip.replaceAll("0*(\\d{3})","$1");
System.out.println(ip);

String[] arr=ip.split(" +");
TreeSet<String> ts=new TreeSet<String>();
for (String s: arr)
{
ts.add(s);
}

for(String s:ts)
{
System.out.println(s.replaceAll("0*(\\d+)","$1"));
}
}

/*
对邮箱校验
*/
public static void checkMail()
{
String mail="avbdgf@sina.com.cn.hah.hgh";
//@前边固定,后边不固定

//可以有下划线 没下划线      没数字下划线
String regex="\\w{6,12}@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}";//较为精准的匹配
System.out.println(mail.matches(regex));

//regex="\\w+@\\w+(\\.\\w+)+";//相对不太精准的匹配
/*
mail.indexOf("@")!=-1  //建立在大部分人都对邮箱格式熟知的基础上
*/
}
}


网页爬虫:

import java.io.*;
import java.net.*;
import java.util.regex.*;
class RegexTest3
{
public static void main(String[] args) throws Exception
{
//getMailsByIE();
getMails();
}

/*
获取指定文档中的邮件地址
包含获取操作,需要用到Pattern和Matcher类
*/
public static void getMails()throws Exception
{
BufferedReader bufr=new BufferedReader(new FileReader("mail.txt"));

Pattern p= Pattern.compile("\\w{5,12}@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}");

String line=null;

PrintWriter out=new PrintWriter(new FileOutputStream("mailgeted.txt"),true);

while ((line=bufr.readLine())!=null)
{
Matcher m=p.matcher(line);
while(m.find())
{
out.println(m.group());
//System.out.println(m.group());
}
}
out.close();
bufr.close();
}
/*将网页中获取的邮箱地址存入文件中*/
public static void getMailsByIE()throws Exception
{
//百度贴吧上找了个带回复中有邮箱的网址
URL url=new URL("http://tieba.baidu.com/p/2314539885");
URLConnection uc=url.openConnection();
BufferedReader bufr=new BufferedReader(new InputStreamReader(uc.getInputStream()));
Pattern p= Pattern.compile("\\w{5,12}@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}");

String line=null;
PrintWriter out=new PrintWriter(new FileOutputStream("mailgeted_1.txt"),true);
while ((line=bufr.readLine())!=null)
{
Matcher m=p.matcher(line);
while(m.find())
{
//System.out.println(m.group());
out.println(m.group());
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: