您的位置:首页 > 编程语言 > Java开发

java基础之正则表达式

2015-12-14 23:38 567 查看
        正则表达式是用来操作字符串的规则,我们可以把正则表达式看做一个模板,把字符串放到这个模板中就可以得到我们想要的样子。

一.  正则表达式的简介

1.正则表达式的概念

        正则表达式是一种规则,那么他用特定的符号来表示代码操作,这样就简化了书写,所以学习正则表达式就是学习一些特殊符号的使用,我们先来了解一下正则表达式的常用符号。

(1)字符类

        [abc]表示此位置是否含有此字符

        [^abc]表示此位置除了abc都可以接收

        [a-zA-Z]接收全部字母,不区分大小写

        [a-b[m-p]]表示可以接收a到b和M到p的字符集

        [a-z&&[^bc]]表示接收a到z但是不包含bc

        [a-z&&[^m-p]]表示接收a到z但是不包含m到p的子集

(2)预定义字符类

        .      任何字符

        \ d    数字0-9

        \D    非数字

        \s    空白字符[ \t\n\x0B\f\r]

        \S    非空白字符

        \w    单词字符[a-zA-Z_0-9] ,邮箱使用

        \W   非单词字符

注意点:\ 单独出现时是转义字符,而\d是一个整体,所以要写\\d,在正则中只要出现“\”在使用的时候就得写“\\”

(3)Greedy 数量词

        X?               表示X出现一次或一次也没有

        X*                表示X出现零次或多次

        X+               表示X出现一次或多次

        X{n}            表示X出现恰好 n 次

        X{n,}           表示X出现至少 n 次

        X{n,m}       表示X出现至少 n 次,但是不超过 m 次

(4) 组

        组是正则当中一个非常强大的概念,我们可以把一个表达式封装成组,就是把它放在括号当中,组是有编号的,第一个括号包装的为第一组,在这个组之后还可以继续使用这个组的结果。

        捕获组可以通过从左到右计算括号来编号。例如,在表达式 ((A)(B(C)))中,存在四个这样的组: 第一组:((A)(B(C))),第二组:(A),第三组: (B(C)),第四组: (C),利用“\\+组的编号”来表示是第几组,例如“\\1”就代表着第一组。而获取组中的内容可以使用”&”,他可以把组中的内容拿到。

2.正则表达式的使用

正则表达式可以应用于操作字符串的两个方法中,作为模板来格式化这个字符串,这两个方法分别是:

(1)匹配:matches(String regex)

返回boolean型,用规则匹配整个字符串,如果有一个不匹配就返回假。

        我们通过对一个手机号码进行校验,使用正则的匹配功能,定义一个正则表达式,把手机号码的特点用正则进行描述,然后将手机号码的字符串表现形式按此正则表达式进行匹配。

/*
* 校验手机号
* 1.利用键盘录入信息
* 2.定义正则表达式,描述手机号
* 3.利用matches方法判断手机号是否正确
* */
public class Test1 {
public static void main(String[] args) {
//利用Scanner接收键盘录入手机号
Scanner sc = new Scanner(System.in);
while(true)
{
//获取录入数据
String str = sc.next();
//如果输入“out”程序结束不再录入
if("out".equals(str))
break;
/*定义正则表达式描述手机号信息
* [1]指第一位必须是数字1
* [358]指第二位数字必须是3或5或8
* \\d第二位后必须是数字
* {9}代表第二位后必须有9位数
* */
String regex = "[1][358]\\d{9}";
//判断是录入数据是否是手机号,利用String的matches方法
if(str.matches(regex))
{
System.out.println("您输入手机号正确!");
break;
}else
{
System.out.println("输入错误,请重新输入!");
}
}
}
}

(2)切割:split(String regex)

返回字符串数组,用指定的正则表达式来切割字符串。

注意点:在切割中我们常用正则来切割URL路径,当我们以“\”作为切割的标准时,在定义正则表达式时要写为“\\”,因为在正则中”\”代表转义字符,所以要多加一个“\”,而URL路径中的“\\”在正则中的表现形式是“\\\\”。

public class SplitDemo2 {
public static void main(String[] args) {

split_1();
System.out.println();
split_2();
}
/*
* 正则切割示例1
* 将字符串“小宏    小蓝             小绿   小黑”按空格切割,得到文字。
* */
private static void split_1() {
//定义字符串
String str = "小宏    小蓝             小绿   小黑";
//定义正则,因为要按空格切,空格数目不确定使用+来表示
String regex = " +";
split(str,regex);
/*
* 结果是:
* 	小宏
小蓝
小绿
小黑
* */
}

/*
* 正则切割示例2
* 将一堆字符串按照叠词切割,例如将
* “heimazzxiaohongzzxiaoheizzxiaohua”
* 按照“zz”进行切割。利用组的概念。
* */
private static void split_2() {

String str = "heimazzxiaohongzzxiaoheizzxiaohua";
//定义正则,(.)组代表任意字符,\\1代表着后一位和组是一样的内容
String regex = "(.)\\1";
split(str,regex);
/*
* 结果是:
* 	heima
xiaohong
xiaohei
xiaohua
* */
}
//切割打印功能函数
private static void split(String str, String regex) {
String[] strs = str.split(regex);
for(String s : strs)
{
System.out.println(s);
}
}
}

(3)替换:replaceAll(String regex,String str)

返回字符串,以指定的字符串str替换掉字符串中正则表达式regex所匹配到的内容。

class Test3
{
public static void main(String[] args)
{
//将字符串中的数字替换成数组
String str1 = "xiaohong12adsf3321adfads";
replaceAll(str1,"\\d","#");
//将叠词替换成#
String str2 = "dfasdkkyasdaalslkddddqqffea";
replaceAll(str2,"(.)\\1+","#");
//将重叠字母替换成单个字母:  "$1"
String str3 = "xiaohong hhhhh xiaolv yyyy xiaolan";
replaceAll(str3,"(.)\\1+","$1");
}
//替换功能函数
public static void replaceAll(String str,String reg,String newStr)
{
str = str.replaceAll(reg,newStr);
System.out.println(str);
}
/*
* 结果是:
* 	xiaohong##adsf####adfads
dfasd#yasd#lslk###ea
xiaohong h xiaolv y xiaolan
*
* */
}

(4)获取

        通过正则表达式把符合要求的子串从字符串中取出具体操作步骤为:

        1>将正则表达式封装成对象,把正则表达式封装成对象的类叫做Pattern,这个类是一个工具类,在这个类中有一个方法compile(String regex),他可以将指定的正则表达式封装成Pattern对象。

        2>让正则对象和要操作的字符串相关联,通过Pattern类中的matcher(CharSequence input)方法,将字符串作为参数传入matcher方法中。

        3>关联后获取正则匹配引擎,当调用matcher方法时会返回一个Matcher对象,这个Matcher就是一个匹配引擎,他具有更多的方法来操作与之匹配的字符串。

        4>启动引擎对符合规则的子串进行操作,我们可以通过Matcher的方法find()方法来将规则作用到字符串上,并进行符合规则的子串查找,然后调用group()方法来返回符合规则的子串,这样就完成了利用正则来获取指定子串。

/*
* 利用指定的规则来获取字符串中的子串
* 获取“heima nihao wo shi xiao hong wo lai le”
* 中由四位字符组成的词组
* */
public class Test4 {

public static void main(String[] args) {
String str = "heima nihao,wo shi xiao hong,wo lai le!";
//定义正则,定义四字单词需要用到边界字符“\b”
String regex = "\\b[a-z]{4}\\b";
//把正则封装成对象
Pattern pt = Pattern.compile(regex);
//获取匹配引擎
Matcher mc = pt.matcher(str);
//将正则作用于字符串上,并进行符合规则的查找
while(mc.find())
{
//取出符合规则的子串
String ss = mc.group();
System.out.println(ss);
}
}
}
/*
* 打印:
* 	xiao
hong
* */

3.正则的弊端

        当我们需要的规则越多,定义的正则表达式就越长,这样阅读性越差,一个复杂的正则表达式让人不能一眼就看出他的作用。而且使用正则之后当输入错误无法精准的定位错误出现的原因。

二.   正则表达式的练习

1.  去掉标点和叠词

/*
* 将以下字符串去重复和省略号
* “我我...我我...要....学学学...编....编...程“
* */
public class Test5 {
public static void main(String[] args) {
String str = "我我...我我...要....学学学...编....编...程";
/*分析正则表达式如何定义
* 1.需要去省略号
* 2.去叠词
* */
//去省略号,使用替换
String newStr1 = str.replaceAll("[.]+","");
System.out.println(newStr1);
//去叠词,使用组
String newStr2 = newStr1.replaceAll("(.)\\1+", "$1");
System.out.println(newStr2);
}
}
/*
* 打印:
* 	我我我我要学学学编编程
我要学编程
*/

2.对IP地址进行排序

/*
* 使用正则对一堆ip地址进行排序
* 192.168.0.1 102.23.45.23 10.10.20.10 2.3.3.3 9.132.43.21
*
* 让ip地址按照字符串自然顺序,2排到10的后面,所以要让他们每一段都是3位,
* 即010对应002时,002就排到010的前面。
* 思路:
1.利用正则将每一段的ip地址前补两个0
2.将每一段只保留3位
3.将3位的ip地址进行排序
4.将ip地址进行还原
* */
public class Test6 {

public static void main(String[] args) {
String ip = "192.168.0.1 102.23.45.23 10.10.20.10 2.3.3.3 9.132.43.21";
//补两个0
String newIp1 = ip.replaceAll("(\\d+)", "00$1");
//保留三位
String newIp2 = newIp1.replaceAll("0*(\\d{3})", "$1");
//将三位数的ip地址进行排序
String[] strs = newIp2.split(" +");
Arrays.sort(strs);
//遍历排完序的数组,并将他们还原
for(String s:strs)
{
System.out.println(s.replaceAll("0*(\\d+)", "$1"));
}
}
}
/*
* 打印:
* 	2.3.3.3
9.132.43.21
10.10.20.10
102.23.45.23
192.168.0.1
*
* */

3.网页爬虫,获取网页中邮箱

           我们可以利用正则来匹配网页上的数据,来获取邮箱名,邮箱的正则表达式较为精准的是“\\w+@\\w+(\\.[a-zA-Z]+){1,3}”,这种格式获取到的邮箱绝大多数为正常的。我们来看一下如何在网页上获取邮箱:

/*
* 建立一个网页爬虫,获取网页中的邮箱
* 1.自定义一个URL访问网页
* 2.获取网页中的内容
* 3.定义正则匹配网页中信息,获取到邮箱
* 4.将获取到的邮箱打印出来并写入本地文件中
* */
public class Test7 {

public static void main(String[] args) {
PrintWriter pw = null;
BufferedReader br = null;

try {

//定义输入流,将获取到的邮箱写入到本地文件
pw = new PrintWriter(new FileWriter("e://email.txt"),true);
//自定义客户端访问网页
URL u = new URL("http://www.itheima.com/newhelp/393.html");
URLConnection uc = u.openConnection();
br = new BufferedReader(
new InputStreamReader(uc.getInputStream()));
String line = null;
//定义正则用来匹配邮箱
String regex = "\\w+@\\w+(\\.[a-zA-Z]+){1,3}";
//把正则封装成对象
Pattern p = Pattern.compile(regex);
while((line = br.readLine())!=null)
{
//拿到引擎匹配当前行
Matcher mc = p.matcher(line);
while(mc.find())
{
String str = mc.group();
System.out.println(str);
pw.println(str);
}
}

} catch (Exception e) {
e.printStackTrace();
}finally
{
pw.close();
try {
if(br==null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*
* 打印:
* heima@csdn.net
* */
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: