关闭

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

239人阅读 评论(0) 收藏 举报
分类:
-----------android培训java培训、java学习型技术博客、期待与您交流!---------

正则表达式

        

      符合一定规则的表达式

      

      作用


            用于专门操作字符串


      特点


            用一些特定的符号来表示一些代码操作,这样就简化了书写,所以就是在学习一些特殊符号的使用。


      好处


            可以简化对字符串的复杂操作


      弊端


            符号定义越多,正则越长,阅读性越差。

 

      常见符号


            字符


                  x      字符 x


                  \\     反斜线字符


                  \t     制表符('\u0009')


                  \n    新行(换行)符('\u000A')


                  \r     回车符('\u000D')


                  \f     换页符('\u000C')


                  \a    报警 (bell) 符 ('\u0007')


                  \e    转义符('\u001B')

 

            字符类


                  [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 次

 

            组和捕获


                  捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C)))中,存在四个这样的组:


                        1.   ((A)(B(C)))


                        2.   \A


                        3.   (B(C))


                        4.   (C)


                        组零始终代表整个表达式。在替换中常用$匹配组的内容。

                  

      正则表达式具体操作功能


            1.   匹配


                  Boolean matches(String regex)            用规则匹配整个字符串,只要有一出不符合规则匹配就结束,返回false。

 

                  代码演示

/*
对正则表达式的匹配功能演示

匹配手机号和QQ号
手机号
	13XXXXXXXXX		15XXXXXXXXX		18XXXXXXXXX	

QQ号
	6~12位的纯数字即可,但开头不能是0

*/

class  RegexDemo
{
	public static void main(String[] args) 
	{
		//调用验证方法,并传入要验证的数字
		phoneNumber("13555555555");
		phoneNumber("18555555555");
		phoneNumber("1755555555");

		QQNumber("123215479615");
		QQNumber("0232154");
		QQNumber("123");
		
	}

	//验证手机号方法,构造函数接收字符串
	public static void phoneNumber(String str)
	{
		//来定义手机号的规则,按题意,13.15.18的号段都可以所以第一位是[1]只是肯定的
		//第二位:3,5,8,中的任意一个,所以是[3,5,8]
		//第3到9位:任意数字均可,所以是\\d,为什么要多加一个\呢?因为\在java中是转义字符
		//会把d转成其他的意思,所以要在前面再加一个\就成了\\d因为剩下的是9位,所以是\\d{9}
		String regex = "[1][358]\\d{9}";

		//使用matches()方法,匹配传入的字符串,用boolean类型变量记录注返回值
		boolean b = str.matches(regex);

		//输出返回结果
		System.out.println("您传入的手机号"+str+":"+b);
	}

	//验证QQ号的方法,在构造函数中接收字符串
	public static void QQNumber(String str)
	{
		//定义QQ号的规则,按题意6~12位的纯数字即可,但开头不能是0
		//第一位:[1-9] 数字1-9都可以,就是不能是0
		//剩下好几位:剩下的是纯数字,有0也可以,所以是\\d。
		//除去第一位还剩下5位或者11位,所以是\\d{5,11}任意数字出现至少5次,但不超过11次
		String regex = "[1-9]\\d{5,11}";

		//使用matches()方法,匹配传入的字符串,用boolean类型变量记录注返回值
		boolean b = str.matches(regex);

		//输出返回结果
		System.out.println("您传入的QQ号"+str+":"+b);
	}
}


                        运行结果



      

            2.   切割


                  String[] split(String  regex)            根据给定正则表达式的匹配拆分此字符串。

 

                  代码演示

/*
正则表达式切割代码演示

要提的几点
1.	当以 . 分开字符串时,split方法内要传入"\\.",因为 . 在正则中代表了任意字符
	我们也要用它切所以要区分开加一个\变为"\.",可是\是转义字符会把 . 转成其他意思
	所以再加一个\ 最终变为"\\."
2.	当以 \\ 分开字符串时,split方法内要传入"\\\\"原因同上。
3.	按叠词完成切割,这时就要用到组的概念。因为是叠词,也不知道是什么词叠.
	所以就用 (.) 代表有一个任意字符的一个组,用\\n来获取组中的内容,n就是组的编号
	这里我们只有一个组,也就是第一组,所以是\\1
	把组中的内容拿来用,在后面再加上 + 获取的组中的内容出现了一此或多次
	叠词可能叠一个也可能叠好几个,所以需要 + 
	最终变为"(.)\\1+" 意思就是一个字符出现了一次,然后又出现了一个或多次,所以是叠词
*/
class  RegexDemo2
{
	public static void main(String[] args) 
	{
		//按 . 切
		String[] arr = "123.25.478.sdf.fe.哈哈哈".split("\\.");
		//打印切出来的字符串数组
		print(arr);

		System.out.println("---------我是一条分割线---------");
		//按\\切
		arr = "sdf\\sdf\\54\\8799\\547\\啦啦啦".split("\\\\");
		print(arr);

		System.out.println("---------我是一条分割线---------");
		//按叠词切
		arr = "465555sdfff878988sdffe哇哈哈哈".split("(.)\\1+");
		print(arr);
	}

	//遍历数组方法,方便看效果
	public static void print(String[] arrs)
	{
		for(String str : arrs)
		{
			System.out.println(str);
		}
	}
}


                        运行结果



 

            3.   替换


                  String  replaceAll(String  regex , String  replacement)


                       使用给定的replacement替换此字符串中所有匹配给定的正则表达式的子字符串。

 

                  代码演示

/*
正则表达式替换代码演示

将叠词替换成一个字符

还是叠词,所以还要使用到组的概念。使用(.)\\1+ 代表叠词,
因为还要用叠词的一个字来替换叠词,所以要用到$

$:拿前面规则中的组

$ 和 \1的区别:\n 获取的是同一个规则里面的组。$ 获取的是别的字符串中的组
*/
class  RegexDemo3
{
	public static void main(String[] args) 
	{	
		//定义字符串
		String str = "我我我我我.....一....定定定定.....要要....去....黑.....马!";

		//先将.去掉,将 . 替换成空
		str = str.replaceAll("\\.+","");
		//输出去掉 . 之后的结果
		System.out.println(str);

		System.out.println("---------我是一条分割线---------");
		//定义要被替换的子字符串所要符合的规则,也就是叠词的规则
		String r2 = "(.)\\1+";
		//用叠词中的一个字来替换叠词,使用$1获取前面规则中的第一组。
		str = str.replaceAll(r2 , "$1");
		//输出结果
		System.out.println(str);	
	}
}


                        运行结果



 

            4.   获取


                  将字符串中符合规则的子串取出。

      

                  操作步骤


                        a.   将正则表达式封装成对象


                               例:Pattern  p = Parrern.compile(regex)


                        b.   让正则对象和要操作的字符串相关联,并获取正则匹配引擎(匹配器)


                              获得匹配器对象。通过Pattern中的


                              Matcher  matcher(CharSequence  input)      其中Charsequence实现了String类所以可以直接在参数中传入字符串。


                              例:Matcher m = p.macher(str);


                              个人理解:把Pattern和要操作的字符关联上,取得Matcher对象Matcher对象调用的所有方法都是在用规则去匹配字符串。


                                                规则和字符串都被封装在Matcher对象内部了,所以Matcher才叫匹配器。(方便记忆)


                        c.   通过引擎对符合规则的子串进行操作。

 

                  代码演示


                        注:当同一个匹配器同时调用matches()find()方法时,就产生索引位的改变,不会从第一个字符开始匹配,


                              可能造成数据丢失,因为同一个匹配器只有一个指针

/*
正则表达式获取代码演示
*/
import java.util.regex.*;

class RegexDemo4 
{
	public static void main(String[] args) 
	{
		//调用获取方法
		get();
	}
	//获取方法
	public static void get()
	{
		//定义要获取的字符串
		String str = "jin tian xue xi de tai xin ku le , bu guo wo hui jia you de";
		//打印字符串
		System.out.println(str);
		//定义规则,获取3个字母的单词 \\b为单词边界
		String regex = "\\b[a-z]{3}\\b";

		//将规则封装成对象。
		Pattern p = Pattern.compile(regex);

		//让正则对象和要作用的字符串相关联。获取匹配器对象。
		Matcher m  = p.matcher(str);

		//System.out.println(m.matches());
		//其实String类中的matches方法。用的就是Pattern和Matcher对象来完成的。
		//只不过被String的方法封装后,用起来较为简单。但是功能却单一。
		
		//将规则作用到字符串上,并进行符合规则的子串查找。一个一个找
		while(m.find())
		{
			//使用group方法获取匹配后的结果。
			System.out.println(m.group());
			//start()和end()方法的返回值分别表示匹配后的结果在字符串上的角标位置。
			System.out.println(m.start()+","+m.end());
		}
	}
}


                        运行结果

                  

 

      

      正则表达式有四种功能,在需求下具体使用哪一种功能呢?或者哪几个功能呢?


            思路方式


                  1.   如果只想知道该字符串是对是错,使用匹配。


                  2.   想要将已有的字符串变为另一个字符串,用替换


                  3.   想要按照指定的方式将字符串变成多个字符串,用切割(获取规则以外的字符串)


                  4.   想拿到符合要求的字符串的子串,用获取(获取符合规则的子串)

 

      正则表达式练习


            练习一

/*
正则表达式练习

练习一
将IP地址排序 192.68.1.3 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30

思路
1. 首先先将IP地址的每一段都至少补到3位,因为如10和2 本来是10大,可是先比的是1和2
	所以就变成了2大,这就不对了,所以要补全3位,但有的段已经是3位了,不管,先补
2. 将所有段都只保留后三位
3. 按自然顺序给IP地址排序,可以使用把IP地址存入TreeSet集合中的方法让他们自然排序
4. 将每一段前面的有0的去掉。
*/
import java.util.*;
class  RegexTest1
{
	public static void main(String[] args) 
	{
		//定义要被排序的IP地址
		String ip = "192.68.1.3 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30";

		//定义要被替换的规则,(\\d+) 数字段
		String regex = "(\\d+)";
		//将规则替换为00$1 在前面补两个0,后面数字不变
		ip = ip.replaceAll(regex , "00$1");
		//输出补完0的字符串
		System.out.println("第一步:"+ip);

		//定义要被替换的规则0*(\\d{3}) 前面有零个或多个0 后面是三个整数
		regex = "0*(\\d{3})";
		//将规则替换为 $1 只保留后三位数
		ip = ip.replaceAll(regex , "$1");
		System.out.println("第二步"+ip);

		//将字符串通过空格切割
		String[] arrs = ip.split(" ");

		//定义一个TreeSet集合
		TreeSet<String> ts = new TreeSet<String>();
		//把切割得来的字符数组加入集合中,让它们按自然顺序排序
		for(String str : arrs)
		{
			ts.add(str);
		}
		System.out.println("第三步");
		//定义循环,循环集合中的元素
		for(String s : ts)
		{
			//将多余的0去除,并打印结果
			System.out.println(s.replaceAll("0*(\\d+)","$1"));
		}

	}
}

                  

                  运行结果




            练习二

/*
正则表达式练习二

需求
对邮箱进行检验

*/
class  RegexTest2
{
	public static void main(String[] args) 
	{
		//定义邮箱地址
		String mail = "1235468@qq.com";
		//较为精确的匹配。
		String reg = "[a-zA-Z0-9]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";
		//相对来说不太精确的匹配
		reg = "\\w+@\\w+(\\.\\w+)+";

		//返回结果
		System.out.println(mail.matches(reg));
	}
}

            练习三

/*
正则表达式练习三

需求
网络爬虫,获取一个网页上的所有邮箱

思路
1. 将网址封装成URL对象
2. 连接远程服务器
3. 建立字符输入流,用于读取网页中的字符信息
4. 将正则规则封装成对象
5. 按行读取网页中的信息,将Pattern对象和读取的信息相关联
6. 将规则作用在字符串上,并获取匹配后的结果
*/
import java.io.*;
import java.util.regex.*;
import java.net.*;

class RegexTest3
{
	public static void main(String[] args) throws Exception
	{
		//调取获得邮箱的方法
		getMails();
	}
	//获得邮箱方法
	public static void getMails()throws Exception
	{
		//封装网页地址
		URL url = new URL("http://tieba.baidu.com/p/3552256898");
		//获取远程服务器
		URLConnection conn = url.openConnection();

		//创建读取流,读取网页上的字符内容
		BufferedReader bufIn = 
			new BufferedReader(new InputStreamReader(conn.getInputStream()));
	
		//定义邮箱规则
		String mailreg = "\\w+@\\w+(\\.\\w+)+";
		//将规则封装成对象
		Pattern p = Pattern.compile(mailreg);

		//定义String类型变量
		String line = null;
		//读取网页上内容,进行匹配
		while((line=bufIn.readLine())!=null)
		{
			//让正则对象和要操作的字符串相关联,获取匹配器对象
			Matcher m = p.matcher(line);
			//寻找符合规则的字符串
			while(m.find())
			{
				//获取匹配后的结果,并打印
				System.out.println(m.group());
			}
		}
	}
}


                  运行结果



 

 




谢谢大家的观看~!

-----------android培训java培训、java学习型技术博客、期待与您交流!---------
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:5633次
    • 积分:215
    • 等级:
    • 排名:千里之外
    • 原创:17篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类
    文章存档