黑马程序员—正则表达式


/*
 *正则表达式(Regex):符合一定规则的表达式
 *
 *作用:用于专门操作字符串
 *
 *特点:用一些特定的符号来表示一些代码操作,这样就简化书写,所以学习正则表达式,就是在学习一些特殊符号的使用
 *
 *好处:可以简化对字符串的复杂操作
 *
 *弊端:符号定义越多,正则越长,阅读性越差
 *如:((())())从左向右数左括号,共四组
 *
 *具体操作功能:
 *1、匹配:String matches方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false
 *
 *2、切割:String split();
 *
 *3、替换:String replaceAll();
 *
 *4、获取:将字符串中符合规则的字符串取出
 *   操作步骤:
 *   1、将正则表达式封装成对象
 *   2、让正则对象和要操作的字符串相关联
 *   3、关联后获取正则匹配引擎
 *   4、通过引擎对符合规则的字串儿进行操作,比如取出
 */


/*  1、匹配:
 *  * 匹配前面的子表达式零次或多次(大于等于0次)。例如,zo*能匹配"z"以及"zoo"。*等价于{0,}。
 *  + 匹配前面的子表达式一次或多次(大于等于1次)。例如,"zo+"能匹配"zo"以及"zoo",但不能匹配"z"。+等价于{1,}。 
 * 
 *  对QQ号码进行校验
 *  要求5~15位,0不能开头,只能是数字
 */
class RegexDemo
{
	public static void main(String[] args)
	{
		checkQQ();
	}
	public static void checkQQ()
	{
		String qq="12345";
		int len=qq.length();
		
		if(len>=5 && len<=15)
		{
			if(!qq.startsWith("0"))
			{
				char[] arr=qq.toCharArray();
				boolean flag=false;
				for(int x=0;x<arr.length;x++)
				{
					if(!(arr[x]>='0' && arr[x]<='9'))
					{
						flag=false;
					    break;
					}
				}
				if(flag)
				{
					System.out.println("qq:"+qq);
				}
				else
				{
					System.out.println("出现非法字符");
				}
			}
			else
			{
				System.out.println("不可以以0开头");
			}
		}
		else
		{
			System.out.println("长度错误");
		}
	}
}

//但以上写法太麻烦,所以可以改写为以下形式:
class RegexDemo1
{
	public static void main(String[] args)
	{
		checkQQ();
	}
	public static void checkQQ()
	{
		String qq="12345";
		int len=qq.length();
		
		if(len>=5 && len<=15)
		{
			if(!qq.startsWith("0"))
			{
				try
				{
					long l=Long.parseLong(qq);
					System.out.println("qq:"+1);
				}
				catch(NumberFormatException e)
				{
					System.out.println("出现非法字符.......");
				}
				
			}
			else
			{
				System.out.println("不可以以0开头");
			}
		}
		else
		{
			System.out.println("长度错误");
		}
	}
}
/*
* 以上这种方式,使用了String类中的方法,进行组合完成了需求,但是代码过于复杂,所以我们可以将以上写法改写成正则表达式:
*/
class RegexDemo2
{
	public static void main(String[] args)
	{
		checkQQ();
	}
	public static void checkQQ()
	{
		String qq="12345";
		/*
		 * 数字第一位是1-9之间的数
		 * 数字第二位是0-9之间的数
		 * 第二位数字出现4-14次
		 */
		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+"....不合法");
	}
}


/*
 *[abc]:表示字符串中只能有一个字符,并且第一位必须是a或b或c中的一个,如果有则返回true,如果没有则返回false
 */
class RegexDemo3
{
	public static void main(String[] args)
	{
		demo();
	}
	public static void demo()
	{
		String str="a";
		
		//[abc]:a、b 或 c(简单类)
		String regex="[bcd]";
		boolean b=str.matches(regex);
		System.out.println(b);
	}
}
/*
 * 运行结果为:
 * false
 * 
 * 如果将"a"换成"b",则运行结果为:true
 * 
 * 如果将"a"换成"bd",则运行结果为:false,因为只能规定一个字符
 */

class RegexDemo25
{
	public static void main(String[] args)
	{
		demo();
	}
	public static void demo()
	{
		String str="be";
		
		String regex="[bcd][a-z]";
		boolean b=str.matches(regex);
		System.out.println(b);
	}
}
/*
 * 运行结果为:
 * true
 */


/*
* [^abc]:除了a、b、c以外的任何字符
* 
* \d:数字[0-9]
* \D:非数字[^0-9]
*/

class RegexDemo4
{
	public static void main(String[] args)
	{
		demo();
	}
	public static void demo()
	{
		String str="b9";
		
		/*也可以写为:
		 * String reg="[a-zA-Z][0-9]";*/			 	
		String regex="[a-zA-Z]\\d";//不可以只写"\d",因为"\"是一个转义字符,会把"\"和"d"拆开理解,所以要写成"\\d"
		boolean b=str.matches(regex);
		System.out.println(b);
	}
}
/*
 * 运行结果为:
 * true
 */

/*
 * X?:X代表规则,X?代表紧靠该符号左边的规则出现1次或0次
 * X*:X代表规则,X*代表紧靠该符号左边的规则出现0次或多次
 * X+:X代表规则,X+代表紧靠该符号左边的规则出现1次或多次
 */
class RegexDemo5
{
	public static void main(String[] args)
	{
		demo();
	}
	public static void demo()
	{
		String str="b9";
		
		String reg="[a-zA-Z]\\d?";
		boolean b=str.matches(reg);
		System.out.println(b);
	}
}
/*
 * 运行结果为:
 * true
 */

//X*:代表0次或多次
class RegexDemo6
{
	public static void main(String[] args)
	{
		demo();
	}
	public static void demo()
	{
		String str="b9453";
		
		String reg="[a-zA-Z]\\d*";
		boolean b=str.matches(reg);
		System.out.println(b);
	}
}
/*
 * 运行结果为:
 * true
 */


/*
 * X{n}:恰好n次
 * X{n,}:至少n次
 * X{n,m}:至少n次,但不超过m次
 */
class RegexDemo7
{
	public static void main(String[] args)
	{
		demo();
	}
	public static void demo()
	{
		String qq="1239453";
		
		//这里的[1-9]表示字符串第一个数字是"1-9"之间的数
		//这里的"\d{4,14}表示除了第一位出现"4-14"位的数字
		String regex="[1-9]\\d{4,14}";
		boolean flag=qq.matches(regex);
		if(flag)
			System.out.println(qq+"....is ok");
		else
			System.out.println(qq+"....不合法");
	}
}
/*
 * 运行结果为:
 * 1239453....is ok
 */


/*
 * 练习:
 * 匹配后继号段只有 13xxx 15xxx 18xxxx
 */
class RegexDemo8
{
	public static void main(String[] args)
	{
		checkTel();
	}
	public static void checkTel()
	{
		String tel="18511340086";
		String telReg="1[358]\\d{9}";
		boolean flag=tel.matches(telReg);
		if(flag)
			System.out.println(tel+"....is ok");
		else
			System.out.println(tel+"....不合法");
	}
}
/*
 * 运行结果为:
 * 18511340086....is ok
 */


//2、切割:split
class RegexDemo9
{
	public static void main(String[] args)
	{
		splitDemo();
	}
	public static void splitDemo()
	{
		String str="zhangsan,lisi,wangwu";
		String reg=",";
		String[] arr=str.split(reg);
		
		for(String s:arr)
		{
			System.out.println(s);
		}
	}
}
/*
 * 运行结果为:
 * zhangsan
 * lisi
 * wangwu
 */

class RegexDemo10
{
	public static void main(String[] args)
	{
		splitDemo();
	}
	public static void splitDemo()
	{
		
		String str="zhangsan   lisi   wangwu";
		String reg=" +";//按照多个空格来进行切割
		String[] arr=str.split(reg);
		System.out.println(arr.length);
		
		for(String s:arr)
		{
			System.out.println(s);
		}
	}
}
/*
 * 运行结果为:
 * 3
 * zhangsan
 * lisi
 * wangwu
 */

class RegexDemo11
{
	public static void main(String[] args)
	{
		splitDemo();
	}
	public static void splitDemo()
	{
		
		String str="zhangsan.lisi.wangwu";
		String reg="\\.";//"."在正则表达式中是一个特殊字符,想要切割".",就要转译一下,写为"\\."
		String[] arr=str.split(reg);
		System.out.println(arr.length);
		
		for(String s:arr)
		{
			System.out.println(s);
		}
	}
}
/*
 * 运行结果为:
 * 3
 * zhangsan
 * lisi
 * wangwu
 */

class RegexDemo12
{
	public static void main(String[] args)
	{
		splitDemo("c:\\abc\\a.txt","\\\\");//当按"\\"切时,每一个"\"都需要转译,所以用"\\\\"
	}
	public static void splitDemo(String str,String reg)
	{
		String[] arr=str.split(reg);
		System.out.println(arr.length);
		
		for(String s:arr)
		{
			System.out.println(s);
		}
	}
}
/*
 * 运行结果为:
 * 3
 * c:
 * abc
 * a.txt
 */


/*
 * 按照叠词进行切割
 * (.):表示任意字符
 * \\1:表示与第一组字符相同
 */
class RegexDemo13
{
	public static void main(String[] args)
	{
		splitDemo("erkkdyqquizzo","(.)\\1");
	}
	public static void splitDemo(String str,String reg)
	{
		String[] arr=str.split(reg);
		System.out.println(arr.length);
		
		for(String s:arr)
		{
			System.out.println(s);
		}
	}
}
/*
 * 运行结果为:
 * 4
 * er
 * dy
 * ui
 * o
 */


/*
 * 按照多个叠词进行切割
 * (.):表示任意字符
 * \\1+:表示与第一组字符相同
 */
class RegexDemo14
{
	public static void main(String[] args)
	{
		splitDemo("erkkkkkdyqquizzzo","(.)\\1+");//按叠字完成切割。为了可以让规则的结果被重用,
		                                        //可以将规则封装成一个组,用()完成。组的出现都有编号
		                                        //从1开始,想要使用已有的组可以通过\n(n就是组的编号)的形式来获取
	}
	public static void splitDemo(String str,String reg)
	{
		String[] arr=str.split(reg);
		System.out.println(arr.length);
		
		for(String s:arr)
		{
			System.out.println(s);
		}
	}
}
/*
 * 运行结果为:
 * 4
 * er
 * dy
 * ui
 * o
 */

//3、替换
class RegexDemo15
{
	public static void main(String[] args)
	{
		//将字符串中的数组替换成#。
		String str="wer1389980000ty1234564uiod234345675f";
		
		replaceAllDemo(str,"\\d{5,}","#");//将数字连续超过5个的数组替换成#
	}
	public static void replaceAllDemo(String str,String reg,String newStr)
	{
		str=str.replaceAll(reg,newStr);
		System.out.println(str);
	}
}
/*
 * 运行结果为:
 * wer#ty#uiod#f
 */

class RegexDemo16
{
	public static void main(String[] args)
	{		
		String str="erkktyqqquizzzzzo";//将多个叠词替换成&。
		replaceAllDemo(str,"(.)\\1+","&");//将多个叠词替换成&。不能替换成$,因为他是特殊字符
	}
	public static void replaceAllDemo(String str,String reg,String newStr)
	{
		str=str.replaceAll(reg,newStr);
		System.out.println(str);
	}
}
/*
 * 运行结果为:
 * er&ty&ui&o
 */


class RegexDemo17
{
	public static void main(String[] args)
	{		
		String str="erkktyqqquizzzzzo";//将重叠的字母替换成单个字母。如:zzzzz->z。
		replaceAllDemo(str,"(.)\\1+","$1");//$代表前一个规则中的组,$1代表前一个规则中的第一个组
	}
	public static void replaceAllDemo(String str,String reg,String newStr)
	{
		str=str.replaceAll(reg,newStr);
		System.out.println(str);
	}
}
/*
 * 运行结果为:
 * erktyquizo
 */

/*
 * 4、获取:将字符串中符合规则的字符串取出
 *    操作步骤:
 *    1、将正则表达式封装成对象
 *    2、让正则对象和要操作的字符串相关联
 *    3、关联后获取正则匹配引擎
 *    4、通过引擎对符合规则的子串儿进行操作,比如取出
 *    
 * Pattern类:正则表达式的编译表示形式,他可以描述正则表达式进行封装
 * compile(String regex):将给定的正则表达式编译到模式中
 */
class RegexDemo18
{
	public static void main(String[] args)
	{
		getDemo();
	}
	public static void getDemo()
	{
		String str="123456";
		String reg="[1-9]\\d{4,14}";
		
		//将规则封装成对象
		Pattern p=Pattern.compile(reg);
		
		//让正则对象和要作用的字符串相关联
		Matcher m=p.matcher(str);
		
		/* 其实String类中的matches方法用的就是Pattern和Matcher方法用的就是Pattern和Matcher对象来完成的
		 * 只不过被String的方法封装后,用起来较为简单,但是功能却单一*/			 
		System.out.println(m.matches());	
	}
}
/*
 * 运行结果为:
 * true
 */


//找出一下字符串中连续三个字母组成的单词
class RegexDemo19
{
	public static void main(String[] args)
	{
		getDemo();
	}
	public static void getDemo()
	{
		String str="ming tian jiu yao fang jia le,da jia";
		String reg="[a-z]{3}";
		
		//将规则封装成对象
		Pattern p=Pattern.compile(reg);
		
		//让正则对象和要作用的字符串相关联
		Matcher m=p.matcher(str);
		
		//find()将规则作用在字符串上,并进行符合规则的子串查找
		boolean b=m.find();
		System.out.println(b);
		
		/*group()用于获取匹配后的结果,如果前面不写find()方法则获取失败,
		 *因为find()方法是匹配,不写find()就是没有匹配过,怎么会获取呢?*/
		System.out.println(m.group());
	}
}
/* 运行结果为:
 * true
 * min
 * 取出了min,但以上写法,一次只能找到一组,改为:
 */
class RegexDemo29
{
	public static void main(String[] args)
	{
		getDemo();
	}
	public static void getDemo()
	{
		String str="ming tian jiu yao fang jia le,da jia";
		String reg="[a-z]{3}";
		
		//将规则封装成对象
		Pattern p=Pattern.compile(reg);
		
		//让正则对象和要作用的字符串相关联
		Matcher m=p.matcher(str);
		
		boolean b=m.find();
		System.out.println(b);
		System.out.println(m.group());
		
		boolean b1=m.find();
		System.out.println(b1);
		System.out.println(m.group());
	}
}
/*
 * 运行结果为:
 * true
 * min
 * true
 * tia
 * 
 * 发现类似迭代器,先找,找到了取出,再找,找到再取出……,想要一次都找出来就需要写循环:
 */

class RegexDemo20
{
	public static void main(String[] args)
	{
		getDemo();
	}
	public static void getDemo()
	{
		String str="ming tian jiu yao fang jia le,da jia";
		String reg="[a-z]{3}";
		
		//将规则封装成对象
		Pattern p=Pattern.compile(reg);
		
		//让正则对象和要作用的字符串相关联
		Matcher m=p.matcher(str);
		
		while(m.find())
		{
			System.out.println(m.group());
		}
	}
}
/* 运行结果为:
 * min
 * tia
 * jiu
 * yao
 * fan
 * jia
 * jia
 * 
 * 发现以上代码虽然取出了连续三个字母的组,但这些组并不都是单词,所以改写为:
 * "\b":单词边界
 * "\B":非单词边界
 */
class RegexDemo21
{
	public static void main(String[] args)
	{
		getDemo();
	}
	public static void getDemo()
	{
		String str="ming tian jiu yao fang jia le,da jia";
		String reg="\\b[a-z]{3}\\b";
		
		//将规则封装成对象
		Pattern p=Pattern.compile(reg);
		
		//让正则对象和要作用的字符串相关联
		Matcher m=p.matcher(str);
		
		while(m.find())
		{
			System.out.println(m.group());
			System.out.println(m.start()+"..."+m.end());//找到获取单词所在的位置,包含头不包含尾
		}
	}
}
/*
 * 运行结果为:
 * jiu
 * 10...13
 * yao
 * 14...17
 * jia
 * 23...26
 * jia
 * 33...36
 */

class RegexDemo30
{
	public static void main(String[] args)
	{
		getDemo();
	}
	public static void getDemo()
	{
		String str="ming tian jiu yao fang jia le,da jia";
		String reg="\\b[a-z]{3}\\b";
		
		//将规则封装成对象
		Pattern p=Pattern.compile(reg);
		
		//让正则对象和要作用的字符串相关联
		Matcher m=p.matcher(str);
		
		System.out.println("matches:"+m.matches());
		
		while(m.find())
		{
			System.out.println(m.group());
			System.out.println(m.start()+"..."+m.end());//找到获取单词所在的位置,包含头不包含尾
		}
	}
}
/*
 * 运行结果为:?
 * matches:false
 * jiu
 * 10...13
 * yao
 * 14...17
 * jia
 * 23...26
 * jia
 * 33...36
 */


/*
 * 需求:
 * 将下列字符串转成:我要学编程
 * 
 * 到底用四种功能中的哪一个呢?或者哪几个呢?
 * 思路方式:
 * 1、如果只想知道该字符串是对是错,可以使用匹配。
 * 2、想要将已有的字符串变成另一个字符串,替换
 * 3、想要按照自己的方式将字符串变成多个字符串。切割,获取规则以外的子串
 * 4、想要拿到符合要求的字符串子串,获取,获取符合规则的子串
 */
class RegexDemo22
{
	public static void main(String[] args)
	{
		test_1();
	}
	public static void test_1()
	{
		String str="我我...我我...我要...要要...要要...学学学...学学...编编编...编程...程..程程..程";
		/*
		 * 将已有字符串变成另一个字符串。使用替换功能
		 * 1、可以先将"."去掉。
		 * 2、再将多个重复的内容变成单个内容。
		 */
		str=str.replaceAll("\\.+","");
		System.out.println(str);
		
		str=str.replaceAll("(.)\\1+","$1");
		System.out.println(str);
	}
}
/*
 * 运行结果为:
 * 我我我我我要要要要要学学学学学编编编编程程程程程
 * 我要学编程
 */

/*
 * 192.68.1.254 102.49.23.13 10.10.10.10 2.2.2.2 8.109.90.30
 * 将ip地址进行地址段顺序的排序
 *  
 * 还按照字符串自然顺序排序,只要让他们每一段都是3位即可
 * 1、按照每一段需要的最多的0进行补齐,那么每一段就会至少保证有3位
 * 2、将每一段只保留3位。这样,所有的ip地址都是每一段3位
 */
class RegexDemo23
{
	public static void main(String[] args)
	{
		ipSort();
	}
	public static void ipSort()
	{
		String ip="192.68.1.254 102.49.23.13 10.10.10.10 2.2.2.2 8.109.90.30";
		
		ip=ip.replaceAll("(\\d+)","00$1");
		System.out.println(ip);
		
		ip=ip.replaceAll("0*(\\d{3})","$1");//"0*"代表没有0或有多个0
		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"));//将所有0都去掉
		}
	}
}
/*
 * 运行结果为:
 * 00192.0068.001.00254 00102.0049.0023.0013 0010.0010.0010.0010 002.002.002.002 008.00109.0090.0030
 * 192.068.001.254 102.049.023.013 010.010.010.010 002.002.002.002 008.109.090.030
 * 2.2.2.2
 * 8.109.90.30
 * 10.10.10.10
 * 102.49.23.13
 * 192.68.1.254
 */

/*
* 需求:对邮件地址进行校验
*/
class RegexDemo24
{
	public static void main(String[] args)
	{
		checkMail();
	}
	public static void checkMail()
	{
		String mail="abc12@sina.com.cn";
		String reg="[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}";//较为精确的匹配
		
		//\w:匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。
		//String reg="\\w+@\\w+(\\.\\w+)+";//不太精确的匹配,124@12.4也会匹配,所以是不太精确的匹配
		
		System.out.println(mail.matches(reg));
	}
}
/*
 * 运行结果为:
 * true
 */

/*
* 网页爬虫(蜘蛛)
*/

/*
* 获取指定文档中的邮件地址
* 使用获取功能:Pattern Matcher
*/
class RegexTest
{
	public static void main(String[] args)throws Exception
	{
		getMail();
	}
	public static void getMail()throws Exception
	{
		//"mail.txt"是有很多文件名、地址明、邮箱名的一个文件
		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())
			{
				System.out.println(m.group());
			}
		}
	}
}


/*
 *在网页上怎么获取邮箱
 */
class RegexTest1
{
	public static void main(String[] args)throws Exception
	{
		getMail_1();
	}
	
	public static void getMail_1()throws Exception
	{
		URL url=new URL("http://tieba.baidu.com/p/2169646694");
		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())
			{
				System.out.println(m.group());
			}
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值