Java正则表达式

概念:

   正则表达式:符合一定的规则的表达式,实际是用来操作字符串的一些规则。 

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

   好处:正则的出现,对字符串的复杂操作变得更为简单。

   特点:将对字符串操作的代码用一些符号来表示。只要使用了指定符号,就可以调用底层的代码对字符串进行操作。符号的出现,简化了代码的书写。

   弊端:符号的出现虽然简化了书写,但是却降低了阅读性。

   其实更多是用正则解决字符串操作的问题。

   组:用小括号标示,每定义一个小括号,就是一个组,而且有自动编号,从1开始。只要使用组,对应的数字就是使用该组的内容。别忘了,数组要加\\。(aaa(wwww(ccc))(eee))技巧,从左括号开始数即可。有几个左括号就是几组。

正则表达式的具体操作功能:

一.匹配(match):

String match方法。用规则匹配整个字符串。只要有一处不符合规则,就匹配结束,返回false。

例1代码:

String str="abc efg ABC"; 
 
String regEx="a|f"; //表示a或f 
 
 Pattern p=Pattern.compile(regEx); 
 
 Matcher m=p.matcher(str); 
 
boolean rs=m.find();

提示:如果str中有regEx,那么rs为true,否则为flase。如果想在查找时忽略大小写,则可以写成Pattern p=Pattern.compile(regEx,Pattern.CASE_INSENSITIVE);

例2代码:
String regEx=".+\\\\(.+)$"; 
 
String str="c:\dir1\dir2\name.txt"; 
 
 Pattern p=Pattern.compile(regEx); 
 
 Matcher m=p.matcher(str); 
 
 boolean rs=m.find(); 
 
for(int i=1;i<=m.groupCount();i++){ 
 
 System.out.println(m.group(i)); 
 
 } 

以上的执行结果为c:\dir1\dir2\name.txt,name.txt,提取的字符串储存在m.group(i)中,其中i最大值为m.groupCount();

提示:"\\"匹配"\\\\"

 二.切割(split):

其实用的就是String类中的split方法。

  代码片段:

private static void spilit(){
		
		String regEx="::"; 
		Pattern p=Pattern.compile(regEx); 
		String str="xd::abc::cde"; 
		String[] r=p.split(str); 
	//执行后,r就是{"xd","abc","cde"},其实分割时还有更简单的方法
		
		//String[] r=str.split("::");
	for(String s:r){
		System.out.println(s);
		
}
打印结果为:
xd
abc
cde
切割叠词:

    1.按照叠词完成切割,为了可以让规则的结果被重用。

   2.可以将规则封装成一个组,用()完成,组的出现都有编号从1开始。

    3.想要使用已有的组可以通过\n(n就是组的编号)的形式来获取的。

代码如下:

private static void overlapsp() {
		String regEx = "(.)\\1+";
		String str = "abbcdddddefffffgz";
		Pattern p = Pattern.compile(regEx);
		String arr[] = p.split(str);
		for (String s : arr) {
			System.out.println(s);

		}

	}
打印结果:
a
c
e
gz

三.替换(replace)

替换:其实用的就是String类中的replaceAll();

需求:将字符串"aaabbced a ccdeaa"中连续的a替换为A

代码如下:

private static void replace() {
		String regEx = "a+"; // 表示一个或多个a
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher("aaabbced a ccdeaa");
		String s = m.replaceAll("A");

		System.out.println(s);

}
打印结果为:
Abbced A ccdeA

四.查找()获取:

1)先要将正则表达式编译成正则对象。使用的是Pattern中静态方法 compile(regex);

2)通过Pattern对象获取Matcher对象。

   Pattern用于描述正则表达式,可以对正则表达式进行解析。

   而将规则操作字符串,需要从新封装到匹配器对象Matcher中。然后使用Matcher对象的方法来操作字符串。

   如何获取匹配器对象呢? 

   通过Pattern对象中的matcher方法。该方法可以正则规则和字符串想关联。并返回匹配器对象。

3)使用Matcher对象中的方法即可对字符串进行各种正则操作。

需求:将字符串”ming tian jiuyao fangjia le, da jia“中连续出现四个字符的子串查找获取出来并打印。

实现代码如下:

private static void getDemo() {
	// TODO Auto-generated method stub
	String str="ming tian jiuyao fang jia le,da jia";
   String reg="\\b[a-z]{4}\\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());
  }
}
打印结果:
ming
0...4
tian
5...9
fang
17...21
五.综合练习:

问题:将下列字符串转成:我要吃饭"。到底用四种功能的哪一种呢?或者是哪几个呢?

思路方法:

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

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

3.想要将已有的字符串变成另一字符串:替换。

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

代码如下:

private static void test1(){
		String str="我我....要要....吃吃....饭饭...";
		str =str.replaceAll("\\.+", "");
		System.out.println(str);
		str=str.replaceAll("(.)\\1+", "$1");
 //$1代表第一组,若replace方法后写的是类似$1 $2 $3...表示用第1 2 3...组去替代原来符合第一个参数正则表式
	       //(xx(xx(A)))\\n中的\\n表示这里捕获引用了第n组。
  System.out.println(str);
		
	}
打印结果如下:
我我要要吃吃饭饭
我要吃饭

另外一个关于组的事例代码:

问题:

将:192.168.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30按照大小排序并打印                   

思路:                                                                                       

1.按照没一段需要的最多的0进行补充,那么每一段就会至少保证有3位                                                
2.将每一段只保留3位。这样。所有的ip地址都是每一段三位,然后按照自然排序对不同的ip排序,并把前面的0去掉打印。 

private static void ipSort(){

String ip="192.168.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30";
/*ip=ip.replaceAll("0*(\\d+)", "00$1");
System.out.println(ip);*/
ip=ip.replaceAll("(\\d+)", "00$1");
System.out.println(ip);
ip=ip.replaceAll("0*(\\d{3})","$1");
//其实第一个参数正则表达式还有其他两种写法:0*(\\d+?)跟0*(\\d++),但0*(\\d+?)这种写法会得出错误结//果,这是与量词有关稍 后会做出解释

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){
s=s.replaceAll("0*(\\d+)","$1");
System.out.println(s);
}
}

打印结果为:

00192.00168.001.00254 00102.0049.0023.00013 0010.0010.0010.0010 002.002.002.002 008.00109.0090.0030
192.168.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.168.1.254

六.正则表达式的量词:

1.Greedy 数量词:          

X? X,一次或一次也没有 
X* X,零次或多次 
X+ X,一次或多次 
X{n} X,恰好 n 次 
X{n,} X,至少 n 次 
X{n,m} X,至少 n 次,但是不超过 m 次 
2.Reluctant 数量词:
X?? X,一次或一次也没有 
X*? X,零次或多次 
X+? X,一次或多次 
X{n}? X,恰好 n 次 
X{n,}? X,至少 n 次 
X{n,m}? X,至少 n 次,但是不超过 m 次 
3.Possessive 数量词:
X?+ X,一次或一次也没有 
X*+ X,零次或多次 
X++ X,一次或多次 
X{n}+ X,恰好 n 次 
X{n,}+ X,至少 n 次 
X{n,m}+ X,至少 n 次,但是不超过 m 次 

4.它们之间的差别:

   正则表达式默认是贪婪匹配(Greedy),可以理解为最大范围匹配。可如果是非贪婪匹配(Reluctant)他就尽可能小的匹配。侵占匹配(possessive)在匹配不成功后不会产生回溯,一般很少用到,只有在正则表达式优化中会用到
   贪婪在匹配不成功后会产生回溯。

   以下是的代码反映三者区别:      

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexDemo2 {
	public static void main(String args[]) {
		Demo2();

	}

	private static void getDemo() {
		// TODO Auto-generated method stub
		String str = "ming tian jiuyao fang jia le,da jia";
		String reg = "\\b[a-z]{4}\\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());
		}
	}

	private static void Demo2() {

		String str="008.109.090.030";
		String reg="0+(\\d+)";//Greedy 数量词
		Pattern p=Pattern.compile(reg);
		 Matcher m=p.matcher(str);
		  while( m.find() ){
			  System.out.print(m.group()+"--->");
			   int len= m.groupCount();
			   System.out.print(len+"-----");
			   for(int i=0;i<=1;i++){
				   System.out.print("group"+"("+i+"):"+m.group(i)+"  ");
			   }
			   System.out.println("       ");
		  }
		  System.out.println("++++++++++++++++++++++++++++++++++++++");
		   
		  String str1="008.109.090.030";
			String reg1="0+(\\d+?)";//Reluctant 数量词
			Pattern p1=Pattern.compile(reg1);
			 Matcher m1=p1.matcher(str1);
			  while( m1.find() ){
				  System.out.print(m1.group()+"--->");
				   int len= m1.groupCount();
				   System.out.print(len+"-----");
				   for(int i=0;i<=1;i++){
					   System.out.print("group"+"("+i+"):"+m1.group(i)+"  ");
				   }
				   System.out.println("       ");
			  }
			
               
			}
	}

结果:
008--->1-----group(0):008  group(1):8         
09--->1-----group(0):09  group(1):9         
090--->1-----group(0):090  group(1):90         
030--->1-----group(0):030  group(1):30         
++++++++++++++++++++++++++++++++++++++
008--->1-----group(0):008  group(1):8         
09--->1-----group(0):09  group(1):9         
09--->1-----group(0):09  group(1):9         
03--->1-----group(0):03  group(1):3 

程序结果分析:

String reg="0+(\\d+)";//Greedy 数量词

008--->1-----group(0):008  group(1):8         

09--->1-----group(0):09  group(1):9         
90--->1-----group(0):090  group(1):90         
030--->1-----group(0):030  group(1):30         
这个表达式的匹配规则就是0开头的数字字符串,表达式’\\d‘表示数字匹配,‘+’表示一次或多次匹配前面的字符
++++++++++++++++++++++++++++++++++++++
String reg1="0+(\\d+?)"
008--->1-----group(0):008  group(1):8         
09--->1-----group(0):09  group(1):9         
09--->1-----group(0):09  group(1):9         
03--->1-----group(0):03  group(1):3 

表达式中的‘?’表示当此字符紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后时,匹配模式是“非贪心的”。“非贪心的”模式匹配搜索到的、尽可能短的字符串,而默认的“贪心的”模式匹配搜索到的、尽可能长的字符串。例如,在字符串“oooo”中,“o+?”只匹配单个“o”,而“o+”匹配所有“o”,近似于String reg1="0+(\\d)"表达式。



           




















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值