正则表达式、正则表达式常用功能、匹配器、URL

1  正则表达式——功能:匹配、切割、替换

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

      作用:用于专门操作字符串。

      特点:用一些特定的符号来表示一些代码操作,这样简化了书写。

                 所以学习正则表达式,就是在学习一些特殊符号的使用。

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

      弊端:符号定义越多,正则表达式越长,阅读性越差。

 

正则表达式功能:

      1,匹配:String类中的 matches方法。

            matches( regex):用正则表达式的规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false

      2,切割:String类中的 split方法。

            split( regex):根据正则表达式split进行切割当前字符串str

      3,替换:String类中的 replaceAll方法。

            replaceAll( regex, newStr):根据正则表达式的规则,用新字符串替换正则表达式定义的字符串。

2  正则表达式规则

字符 :

      x   字符 

      \\   反斜线字符 

      \0n   带有八进制值 的字符 n (0 <= n <= 7) 

      \0nn   带有八进制值 的字符 nn (0 <= n <= 7) 

      \0mnn   带有八进制值 的字符 mnn0 <= m <= 30 <= n <= 7) 

      \xhh   带有十六进制值 0x 的字符 hh 

      \uhhhh   带有十六进制值 0x 的字符 hhhh 

      \t   制表符 ('\u0009') 

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

      \r   回车符 ('\u000D') 

      \f   换页符 ('\u000C') 

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

      \b   匹配一个单词边界,也就是指单词和空格间的位置 

      \e   转义符 ('\u001B') 

      \cx   对应于 的控制符 

 

字符类:

      [abc]   a或 c(简单类) 

      [^abc]   任何字符,除了 a或 c(否定) 

      [a-zA-Z]   a 到 或 到 Z,两头的字母包括在内(范围) 

      [a-d[m-p]]   a 到 或 到 p[a-dm-p](并集) 

      [a-z&&[def]]   d或 f(交集) 

      [a-z&&[^bc]]   a 到 z,除了 和 c[ad-z](减去) 

      [a-z&&[^m-p]]   a 到 z,而非 到 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] 

 

Greedy 数量词:

      X?   X,一次或一次也没有 

      X*   X,零次或多次 

      X+   X,一次或多次 

      X{n}   X,恰好 次 

      X{n,}   X,至少 次 

      X{n,m}   X,至少 次,但是不超过 次。 

 

3  组和捕获及正则表达式实例

组合捕获

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

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

      2   \A 

      3   (B(C)) 

      4   (C) 

0始终代表整个表达式。 

 

之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。

捕获的子序列稍后可以通过 Back 引用在表达式中使用,也可以在匹配操作完成后从匹配器获取。 

 

与组关联的捕获输入始终是与组最近匹配的子序列。如果由于量化的缘故再次计算了组,

则在第二次计算失败时将保留其以前捕获的值(如果有的话)例如,将字符串 "aba" 与表达式 (a(b)?)+ 相匹配,

会将第二组设置为 "b"。在每个匹配的开头,所有捕获的输入都会被丢弃。 

 

以 (?) 开头的组是纯的非捕获组,它不捕获文本,也不针对组合计进行计数。

 

应用实例:

需求:对QQ号码进行校验,要求:515位,0不能开头,只能是数字。

原方式:这种方式使用String类中的方法,进行组合完成了需求。但是代码过于复杂。

 

代码示例:

class RegexDemo{
	public static void main(String[] args){
		checkQQ_1();
		checkQQ();
		demo();
		splitDemo();
		
		String str = "wer1389980000ty12345uiod2345452452454f";//将字符串中数字替换成# 
		replaceAllDemo(str,"\\d{5,}","#");  //\\d{5,}:连续0到9的数字至少5个。
		
		String strr = "erkktytuqqquizzzzzo"; //将叠词替换成相应的单个字符。
		replaceAllDemo(strr,"(.)\\1+","$1");//$1 表示正则表达式中的第一组,即()中的内容,符号$有特殊含义。
	}
	
	//根据正则表达式替换
	public static void replaceAllDemo(String str, String regex, String newStr){
		str = str.replaceAll(regex,newStr);  //String类的replaceAll方法,可以用正则替换 
		System.out.println(str);
	}
	
	//根据正则表达式切割字符串
	public static void splitDemo(){
	 /* String str = "zhangsan....lisi...wangwu";
		String regex = "\\.+";  */ //按照多个点来切割,见正则中的Greedy数量词
		
		String str = "crkkadfddalpezzzzkjgf"; 
		
		String regex = "(.)\\1+";  //按照叠词完成切割,可以将规则封装成一个组,用()括起来。
		                       //组的出现都有编号,从1开始。想要使用已有的组可以通过 \n的形式获取,n是编号
		
		String[] arr = str.split(regex); //根据叠词分割
		for(String s : arr){
			System.out.println(s);
		}
	}
	
	//正则表达式定义规则:字符,字符类,预定义字符类,Greedy数量词
	public static void demo(){
		String str = "b9";
		
		String regex = "[a-zA-Z]\\d";
		
		boolean b = str.matches(regex); //匹配
		System.out.println(b);
	}
	
	//正则表达式方式
	//boolean matches(String regex); 告知此字符串是否匹配给定的正则表达式。 
	public static void checkQQ(){
		String qq = "275150374";
		
		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+"...不合法");
	}
	
	//原方式,不使用正则表达式。
	public static void checkQQ_1(){
		String qq = "111111111111111";
		int len = qq.length();
		
		if(len>=5 && len<=15){
			if(!qq.startsWith("0")){
							
				char[] arr = qq.toCharArray();
				boolean flag = true;
				
				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("长度错误");
		}
	}
}

4  正则表达式功能——获取(匹配器Matcher)

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

操作步骤:

1,将正则表达式封装成对象。

2,让正则对象和要操作的字符串相关联。

3,关联后,获取正则匹配引擎。

4,通过引擎,对符合规则的子串进行操作,比如取出。

 

代码示例:

import java.util.regex.*;

class RegexDemo2 {
	public static void main(String[] args){
		getDemo();
	}
	public static void getDemo(){
		String str = "ming tian jiu yao fang jia la";
		
		//正则表达式,\b是单词边界符。
		String regex = "\\b[a-z]{4}\\b"; 
		
		//将正则封装成对象。
		Pattern p = Pattern.compile(regex);
		
		//让正则对象和要作用的字符串相关联。获取匹配器对象。
		Matcher m = p.matcher(str);
		
	  //str.matches(regex);//其实String类中的matches方法,用的就是Pattern和Matcher对象来完成的,
						   //只不过被String的方法封装后,用起来较为简单,但是功能却单一。
		
		while(m.find()){  //判断是否有符合匹配器的子串。
			System.out.println(m.group());  //返回由以前匹配操作所匹配的输入子序列,返回匹配结果。
			
			//匹配的子串的开始脚标和结束脚标,包含头不包含尾。
			System.out.println("位置:"+m.start()+"..."+m.end()); 
		}
	}
}

匹配结果:


5  正则表达式练习★

练习1

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

      到底用四种功能中的哪一个呢?或者哪几个呢?

      思路方式:

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

      2,想要将已有的字符串变成另一个字符串,替换。

      3,想要按照自定的方式将字符串变成多个字符串,切割、获取规则以外的子串。

      4,想要拿到符合需求的字符串子串,获取、获取符合规则的子串。

练习2

      需求:将ip地址进行地址段顺序的排序。

                  192.68.1.254  102.49.23.13  10.10.10.10  2.2.2.2  8.109.30.90

      还按照字符串自然顺序,只要让它们每一段都是3位即可。

      1,按照每一段需要的最多的0进行补齐,那么每一段至少保证有3位。

      2,将每一段只保留3位。这样,所有的ip地址段都是每一段3位。

练习3

      需求:对邮件地址进行校验。

 

代码示例:

import java.util.regex.*;
import java.util.*;

class RegexTest{
	public static void main(String[] args){
		test_1();
		ipSort();
		checkMail();
	}
	
	public static void test_1(){
		String str = "我我...我我...我要..要要...要要...学学学..学学..编编...编编..编程..程程.程程";
		
		/* 将已有字符串变成另一个字符串。使用替换功能。
		1,可以先将 “.”去掉。
		2,再将多个重复的内容变成单个内容。 */
		
		str = str.replaceAll("\\.+","");
		System.out.println(str);
		
		//$1 表示正则表达式中的第一组,即()中的内容,符号$有特殊含义.
		str = str.replaceAll("(.)\\1+","$1");
		System.out.println(str);
	}
	
	public static void ipSort(){
		String ip = "192.68.1.254  102.49.23.13  10.10.10.10  2.2.2.2  8.109.30.90";
		
		ip = ip.replaceAll("(\\d+)","00$1"); //每一段都补两个0 
		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>(); //TreeSet集合,自然排序 
		for(String s : arr){
			ts.add(s);
		}
		for(String s : ts){
			System.out.println(s.replaceAll("0*(\\d+)","$1"));  //把开头的0去掉 
		}
	}
	
	public static void checkMail(){
		String mail = "abc123@sina.com";
		
		String reg = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";//较为精确的匹配
		String regex = "\\w+@\\w+(\\.\\w+)+";  //相对不太精确的匹配
		
		System.out.println(mail.matches(regex));
	}
}

6  抓取电子邮件地址和URL

获取指定文档中的邮件地址。

使用获取功能,Pattern  Matcher 

 

URLjava.net包的URL类、URLConnection

调用URL对象的openConnection()方法创建连接对象,返回URLConnection对象。

 

URLConnection类中

      getInputStream():返回从此打开的链接读取数据的读取流,读取URL资源。

      getOutputStream():返回写入到此链接的输出流。

代码示例:

import java.util.regex.*;
import java.io.*;
import java.net.*;

class RegexTest2 {
	public static void main(String[] args) throws Exception{
		getMails();
		getMails_1();
	}
	
	//从文档中抓取电子邮件地址
	public static void getMails() throws Exception{
		BufferedReader bufr = 
			new BufferedReader(new FileReader("e:\\mail.txt"));
		
		String mailregex = "\\w+@\\w+(\\.\\w+)+";
		Pattern p = Pattern.compile(mailregex);//将正则封装成对象
		
		String line = null;		
		while((line=bufr.readLine())!=null){
			Matcher m = p.matcher(line); //正则对象和字符串关联,获取匹配器
			
			while(m.find()){ //是否有符合匹配器的子串。
				System.out.println(m.group()); //返回匹配的子序列,返回匹配结果。
			}
		}
	}
	
	//从网页中抓取电子邮件地址
	public static void getMails_1() throws Exception{
		URL url = new URL("http://192.168.0.100:8080/myweb/mail.html");
		
		URLConnection conn = url.openConnection(); //创建连接对象。
		
		BufferedReader bufIn = 
			new BufferedReader(new InputStreamReader(conn.getInputStream())); //读取URL资源的读取流
		
		String mailregex = "\\w+@\\w+(\\.\\w+)+";
		Pattern p = Pattern.compile(mailregex); //把正则表达式封装成对象
		
		String line = null;		
		while((line=bufIn.readLine())!=null){
			Matcher m = p.matcher(line); //创建匹配器,关联正则对象和字符串
			
			while(m.find()){  //判断是否有匹配的子串
				System.out.println(m.group()); //返回匹配结果
			}
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值