代码改变世界

Java 正则中的(.*?)vs(.*)

2012-07-23 11:11  java线程例子  阅读(242)  评论(0编辑  收藏  举报

@author YHC

public static void main(String[] args) {

        //选择最小和最大重复次数
		String a="{user=\"administrator\",password=\"root\"}";
		String b="user   =\"a\"";//注意=号之间有空格
		String c="user\r\n=\"c\"";//注意有换行符号
		
		//获取双引号之间的内容,分别获得a,b,c中的所有的用户的名称
		String regex="(?s)user.*?=(\".*?\")";
		match(regex,a);//user="administrator"
		match(regex,b);//user   ="a"
		match(regex,c);//user
                       //="c"
		
		//上面的非常简单,注意以下事例
		//选择最小和最大重复数
		//注意以下几点,user =这个之间可能有空格
		//我们需要的结果是找出user='xxx'的信息,其余不要
		String notice="[{user='admin',password='admin'}," +
				       "{user='yhc',password='yhc'}]";
		//也许大家会觉得.*?为什么需要?号,那么一下我们看看
		//有?和没有?的区别
		String regex1="user.*='(.*?)'";//user.*=之间没有?
		match(regex1, notice);
		//输出结果(错误):user='admin',password='admin'},{user='yhc',password='yhc'
		
		String regex2="user.*?='(.*?)'";//user.*=之间有?
		match(regex2, notice);
		//输出结果(正确):
		//user='admin'
		//user='yhc'
		
		//为什么上面就因为一个?号而有这么大的区别咧?
		//解释以上代码运行机制
		//有了匹配文本中的第一个user之后,引擎就会到达(.*),其中点号(.)可以
		//匹配任意字符,其中包括换行符,星号(*)则把它重复0次或更多次,请注意,
		//这里的星号(*)是贪心的,因此点星(.*)会匹配直到目标文件结束的所有的
		//内容,注意=====>>>>(.*)会吃了所有的目标文件内容,从第一个匹配
		//user的地方开始;
		
		//当(.*)把肚子吃饱之后,引擎才会试图去匹配在目标文本末尾的=
		//这个表达式,当然,一定会匹配失败,但这并不会代表此次匹配就结束了,
		//正则引擎会进行回溯backtrack,当匹配某一个位置之后
		//,正则表达式都会保存一个回溯位置,如果正则表达式匹配之后的文本失败后
		//那么正则引擎还可以回到这些位置
		//当=匹配匹配失败之后,引擎进行回溯,让(.*)放弃它的匹配中的一个
		//字符接着=会被再次尝试匹配,这次在文本中的最后一个字符的位置,
		//如果依然失败的话,那么引擎会再一次进行回溯在文件的倒数第2个字符出尝试匹配
		//这个过程会一直继续,直到=匹配成功位置,如果一直没有匹配成功,那么最终(.*)
		//会用完所有的回溯位置,然后正则匹配失败
		
		//如果在整个回溯的过程中=在某个点匹配成功,那么就会接着尝试匹配'如果'匹配
		//失败,引擎接着进行回溯,这个过程会一直重复,直到='(.*?)'可以被匹配为止
		
		//问题就出现在.*上,因为星号是贪心的,所以你们要注意哦!
		//我们需要使用lazy 懒惰 可以在后面放一个?使其变为懒惰
		//例如:(*?),(+?),(??) ,{1,100}? 都可以将其变为懒惰	
		
	}
	
	public static void match(String regex,String input){
		    //创建正则对象
       		Pattern pattern=Pattern.compile(regex);
       		//匹配对象
       		Matcher matcher=pattern.matcher(input);
       		//输出匹配字符串
       		while(matcher.find()){
       			System.out.println(matcher.group());
       		}
	}

如果以上有写错误的地方,请大家指出,thanks!