黑马程序员 java_正则表达式笔记

时间:2023-02-19 09:33:31

-------android培训 、java培训、期待与您交流! ----------

正则表达式

 在编写处理祖父穿的程序或者网页时,经常会有查找符合某些复杂规则的字符串的需要,正则表达式就是用于描述这些规则的工具,即是记录文本规则的代码。

作用用于专门操作字符串  是操作字符串的规则.

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

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

 弊端  符号定义越多正则越长 阅读性越差.

黑马程序员 java_正则表达式笔记黑马程序员 java_正则表达式笔记

\ba\w*\b匹配以字母a开头的单词——先是某个单词开始处(\b),然后是字母a,然后是任意数量的字母或数字(\w*),最后是单词结束处(\b)。

\d+匹配1个或更多连续的数字。这里的+是和*类似的元字符,不同的是*匹配重复任意次(可能是0次),而+则匹配重复1次或更多次

\b\w{6}\b 匹配刚好6个字符的单词

元字符^(和数字6在同一个键位上的符号)和$都匹配一个位置,这和\b有点类似。^匹配你要用来查找的字符串的开头,$匹配结尾。这两个代码在验证输入的内容时非常有用,比如一个网站如果要求你填写的QQ号必须为5位到12位数字时,可以使用:^\d{5,12}$

这里的{5,12}和前面介绍过的{2}是类似的,只不过{2}匹配只能不多不少重复2次{5,12}则是重复的次数不能少于5次,不能多于12次,否则都不匹配。

因为使用了^$,所以输入的整个字符串都要用来和\d{5,12}来匹配,也就是说整个输入必须是5到12个数字,因此如果输入的QQ号能匹配这个正则表达式的话,那就符合要求了。

采用上面的方法,只能保证在该字符串中包含5 到12个数字。

同样是QQ号匹配还可以用另外一种方式 [1-9]\\d{4,14} [1-9]表示第一位只能是1-9中的一个数字,\\d{4,14}表示接下来是4-14为数字

public static void checkQQ()
	{
		String qq="1232434534";
		String regex = "[1-9]\\d{4,14}";
		boolean flag =qq.matches(regex);
		if(flag)
			sop(qq+"-----ok--");
		else
			sop(qq+"--no-no-");
	}
	public static void checkQQ_2()
	{
		String qq= "123qq45678";
		String regex = "[1-9][0-9]{4,14}";
		boolean flag =qq.matches(regex);
		if(flag)
			sop(qq+"-----ok--");
		else
			sop(qq+"--no-no-");
	}

和忽略大小写的选项类似,有些正则表达式处理工具还有一个处理多行的选项。如果选中了这个选项,^$的意义就变成了匹配行的开始处和结束处

[aeiou]就匹配任何一个英文元音字母[.?!]匹配标点符号(.或?或!)

我们也可以轻松地指定一个字符范围,像[0-9]代表的含意与\d就是完全一致的:一位数字;同理[a-z0-9A-Z_]也完全等同于\w(如果只考虑英文的话)。

下面是一个更复杂的表达式:\(?0\d{2}[)-]?\d{8}

这个表达式可以匹配几种格式的电话号码,像(010)88886666,或022-22334455,或02912345678等。我们对它进行一些分析吧:首先是一个转义字符\(,它能出现0次或1次(?),然后是一个0,后面跟着2个数字(\d{2}),然后是)-空格中的一个,它出现1次或不出现(?),最后是8个数字(\d{8})。

分枝条件

不幸的是,刚才那个表达式也能匹配010)12345678(022-87654321这样的“不正确”的格式。要解决这个问题,我们需要用到分枝条件。正则表达式里的分枝条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。听不明白?没关系,看例子:

0\d{2}-\d{8}|0\d{3}-\d{7}这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)

\(0\d{2}\)[- ]?\d{8}|0\d{2}[-]?\d{8}这个表达式匹配3位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号间可以用连字号或空格间隔,也可以没有间隔。你可以试试用分枝条件把这个表达式扩展成也支持4位区号的。

\d{5}-\d{4}|\d{5}这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字,或者用连字号间隔的9位数字。之所以要给出这个例子是因为它能说明一个问题:使用分枝条件时,要注意各个条件的顺序。如果你把它改成\d{5}|\d{5}-\d{4}的话,那么就只会匹配5位的邮编(以及9位邮编的前5位)。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。

分组

我们已经提到了怎么重复单个字符(直接在字符后面加上限定符就行了);但如果想要重复多个字符又该怎么办?你可以用小括号来指定子表达式(也叫做分组),然后你就可以指定这个子表达式的重复次数了,你也可以对子表达式进行其它一些操作(后面会有介绍)。

(\d{1,3}\.){3}\d{1,3}是一个简单的IP地址匹配表达式。要理解这个表达式,请按下列顺序分析它:\d{1,3}匹配1到3位的数字(\d{1,3}\.){3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字(\d{1,3})。

不幸的是,它也将匹配256.300.888.999这种不可能存在的IP地址。如果能使用算术比较的话,或许能简单地解决这个问题,但是正则表达式中并不提供关于数学的任何功能,所以只能使用冗长的分组,选择,字符类来描述一个正确的IP地址:((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

 

需求将下列字符串转成 我要学编程 


我我...我我...我要..要要..要要..学学学..学学..编编编..编程.程程...程..程
分析 到底用四种功能中的哪一个呢,或者哪几个
思路 
1 如果只想知道该字符串是对是错,使用匹配 
2 想要将已有的字符串变成另一个字符串,替换
3 想要按照指定的方式将字符串变成多个字符串, 切割 获取规则以外的子串
4 想要拿到符合需求的字符串子串  获取 获取符合规则的子串


需求2 
一堆地址 
192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30
将ip地址进行地址段顺序的排序


按照字符串自然排序,只要让他们每一段都是3位即可 
1 按照每一段需要的最多的0进行补齐 那么每一段就会至少保证有3位。
2 将每一段只保留3位  这样所有的ip地址都是每一段3位。

class RegexTest 
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		 //test_1();
		// ipSort();
		checkMail();
		
	}
	public static void test_1()
	{
		String str = "我我...我我...我要..要要..要要..学学学..学学..编编编..编程.程程...程..程";
		/*
		将已有字符串编程另一个字符串 使用替换功能
		1 可以先将 .去掉
		2 再将多个重复的内容编程单个内容 
		*/
		str = str.replaceAll("\\.+",""); //一个以上的点替换成空字符串 干掉点
		sop(str);
		str = str.replaceAll("(.)\\1+","$1"); //用组 把叠词干掉
		sop(str);
	}
	public static void ipSort()
	{
		String ip = "192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30";
		// \\d+ 一连串数字  被重用 装组 (\\d+)  00$1 第一位前面补俩0 
		ip = ip.replaceAll("(\\d+)","00$1");
		sop(ip);
		// 0*(\\d{3}) 0 没有或多次共连续3个数
		ip = ip.replaceAll("0*(\\d{3})","$1");
		sop(ip);
		String[] arr = ip.split(" +");
		TreeSet<String> ts = new TreeSet<String>();
		for(String s : arr)
		{
			ts.add(s);
		}
		for(String s : ts)
		{
			sop(s.replaceAll("0*(\\d+)","$1")); //去0 输出
		}
	}
	/*
	需求 对邮件地址进行校验 

	
	*/
	public static void checkMail()
	{
		String mail = "sad2323@163.com.cn";
		//较为精确的匹配
		String reg = "[a-zA-Z0-9_]{6,12}@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}"; 
		reg = "\\w+@\\w+(\\.\\w+)+"; //相对不太精确的匹配
		sop(mail.matches(reg));
	}
}

正则表达式的第四个功能
4 获取 将字符串中符合规则的子串取出 
操作步骤 
1 先将正则表达式封装成对象,
2 让正则对象和 要操作的字符串想关联
3 关联后 获取正则匹配引擎
4 通过引擎对符合规则的子串进行操作,比如取出

import java.util.regex.*;

class RegexDemo2
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		getDemo();
	}
	public static void getDemo()
	{
		String str = "ming tian ju yao fang jia le da jia";
		//str="136546543";
		//String reg = "[1-9]\\d{4,14}";
		String reg = "\\b[a-z]{3}\\b"; // \b 单词结束标记
		//将规则封装成对象
		Pattern p = Pattern.compile(reg);
		//让正则对象和要作用的字符串相关联。 获取匹配器对象
		Matcher m = p.matcher(str);
		//sop(m.matches());//其实String类中的matches方法,用的就是Pattern和Matcher对象来完成的
						//只不过被String的方法封装后,用起来较为简单 但功能却单一 
	//	boolean b = m.find();//将规则作用在字符串上,并进行符合规则的子串查找
	//	sop(b);
		while (m.find())
		{
			sop(m.group());//用于获取匹配后的结果
		}
		
		

	}
}
class  RegexDemo
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
	网页爬虫(蜘蛛) 
		splitDemo("sdaddftterrgcf","(.)\\1+"); //按照叠词完成切割 叠词 后一个跟前一个是一致的
		/*怎么表示后一个跟前一个一样呢
		   . 表示任意字符 
		   把要重用的部分()起来 形成一个重用组这个结果就 这个组封装后悔有一个编号 
		   从1开始 想要使用已有的组可以通过\n的形式获取 n就是租的编号
		   (.)\\1; 表示第一位的内容在第二位又出现了
		   (.)\\1+; 切多个一样的
			((())())  有几个左括号就有几组 这个是由四组第一个左括号是第一次 2是2 3是3 4是4
		*/
	}
	public static void splitDemo(String str,String reg)
	{
		
	    //String reg = " +";//空格符出现了一次或多次 按多个空格来进行切割 
		
		
		
		String[] arr = str.split(reg);
		sop(arr.length);
		for(String s : arr)
		{
			sop(s);
		}
	}
	public static void demo()
	{
		String str = "as";
		//String reg = "[bcd]";//这个字符串中的第一个字符只能是b,c或者d 字符串只能有一个字符
		//String reg = "[bcd][a-z]";// 第一个字符同上 第二个字符只能是小写字母
		String reg = "[a-zA-Z]\\d?";//第一位是个字母 第二位是个数字有可能出现也有可能不出现要么有一个要么没有
		//?变成* 表示后面有0个数字或多个
		boolean  b=str.matches(reg);
		sop(b);
	}
网页爬虫(蜘蛛) 获取网页上的email

import java.io.*;
import java.util.regex.*;
import java.net.*;
class  RegexTest2
{
	public static void main(String[] args) throws Exception
	{
		getMails();
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	/*
	获取指定文档中的邮件地址
	使用获取功能 Pattern Matcher

	
	*/
	//爬网页的
	public static void getMails()throws Exception
	{
		URL url = new URL("http://tieba.baidu.com/p/2219661488");
		URLConnection conn = url.openConnection();//获取连接器
		BufferedReader bufIn=new BufferedReader(new InputStreamReader(conn.getInputStream()));
		String line = null;
		String mailreg = "\\w+@\\w+(\\.\\w+)+"; //简单比对
		Pattern p = Pattern.compile(mailreg); // 封装成对象
		while ((line =bufIn.readLine())!=null)
		{
			Matcher m =p.matcher(line); //正则表达式跟文本相关联并返回到匹配器引擎
			while (m.find())
			{//找一次取一次
				sop(m.group());
			}
		}

	}
	//爬文件的
	public static void getMails_1()throws Exception
	{
		BufferedReader bufr = 
			new BufferedReader(new FileReader("mail.txt"));
		String line = null;
		String mailreg = "\\w+@\\w+(\\.\\w+)+"; //简单比对
		Pattern p = Pattern.compile(mailreg); // 封装成对象
		while ((line =bufr.readLine())!=null)
		{
			Matcher m =p.matcher(line); //正则表达式跟文本相关联并返回到匹配器引擎
			while (m.find())
			{//找一次取一次
				sop(m.group());
			}
		}
	}

}

【参考文献】

http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html

------- android培训  、 java培训 、期待与您交流! ----------