正则表达式小结

学习网址:http://www.w3cschool.cc/java/java-regular-expressions.html

实现目的:每四个数加个空格,数的长度不定。

例子:参考:http://biancheng.dnbcw.info/java/110082.html

	String num1 = "1234562222";
	System.out.println("1234562222".replaceAll("\\d{4}(?!$)", "$0 "));//这句就够了
	//String res = Pattern.compile("\\d{4}(?!$)").matcher(num1).replaceAll("$0 ");
	//System.out.println(res);  
	例子中$0代表匹配的表达式。结果:1234 5622 22

下面是学习期间的一些理解和总结:

(pattern)

匹配 pattern 并捕获该匹配的子表达式。可以使用 $0…$9 属性从结果"匹配"集合中检索捕获的匹配。若要匹配括号字符 ( ),请使用"\("或者"\)"。

注:在正则表达式中,被小括号括起来的子表达式称为捕获组,正则表达式在求值期间将保存匹配这些捕获组表达式的输入子序列。一旦完全匹配操作完成,这些保存的代码片断可通过确定相应的组号从 Matcher对象上重新获取。捕获组可以嵌套使用,数量可以通过从左到右计算左括弧(开括号)得到。无论整个表达式是否有子组,它的捕获组总能记为组零(group zero)。

例如,正则表达式 A((B)(C(D)))可能有的捕获组编号如下所示:

组号    表达式组 
0   A((B)(C(D))) 
1   ((B)(C(D))) 
2    (B) 
3   (C(D)) 
4   (D)

参照下例子理解捕获组

	String num = "dog cast dogg";
	String pattern = "d(o)?(gg?)";
	Pattern r = Pattern.compile(pattern);
	Matcher m = r.matcher(num);
	int count=m.groupCount();
	System.out.println("group个数:"+count);
	if(m.find()){
		System.out.println("group 0: " + m.group(0));
		System.out.println("group 1: " + m.group(1));
		System.out.println("group 2: " + m.group(2));
	}
	
//结果如下:可看出来:()个数就是组个数 而group 0是个特殊的组,它总是代表整个表达式。该组不包括在groupCount的返回值中。
//	group个数:2
//	group 0: dog
//	group 1: o
//	group 2: g

(?=pattern)

执行正向预测先行搜索的子表达式,该表达式匹配处于匹配 pattern 的字符串的起始点的字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,'Windows (?=95|98|NT|2000)' 匹配"Windows 2000"中的"Windows",但不匹配"Windows 3.1"中的"Windows"。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。

(?!pattern)

执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,'Windows (?!95|98|NT|2000)' 匹配"Windows 3.1"中的 "Windows",但不匹配"Windows 2000"中的"Windows"。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。 可理解为 不消耗任何字符,如下例。


细节:(?=exp) 也叫零宽度正预测先行断言

它断言自身出现的位置的后面能匹配表达式exp。比如\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.时,它会匹配sing和danc。

  (?!exp) 也叫零宽度负向预测先行断言

\b\w*q[^u]\w*\b 匹配包含后面不是字母u的字母q的单词。

可是你会发现,如果q出现在单词的结尾的话,像Iraq,Benq,这个表达式就会出错。这是因为[^u]总要匹配一个字符,所以如果q是单词的最后一个字符的话,后面的[^u]将会匹配q后面的单词分隔符(可能是空格,或者是句号或其它的什么),后面的\w*\b将会匹配下一个单词,于是\b\w*q[^u]\w*\b就能匹配整个Iraq fighting。

然而:
负向零宽断言能解决这样的问题,因为它只匹配一个位置,并不消费任何字符。现在,我们可以这样来解决这个问题:\b\w*q(?!u)\w*\b

参考:http://www.cnblogs.com/mu-mu/archive/2013/02/06/2893581.html

注释:(零宽度正预测先行断言)仅当子表达式在此位置的右侧匹配时才继续匹配。例如,\w+(?=\d) 与后跟数字的单词匹配,而不与该数字匹配。

最后一个小例子自己在这犯错了,所以记录一下:

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

public class Test {
	public static void main(String[] args) {
		String s = "<BODY>" + "<H1>Welcome to my Homepage</H1>"
				+ "Content is divided into two sections:<BR>"
				+ "<H2>ColdFusion</H2>"
				+ "Information about Macromedia ColdFusion."
				+ "<H2>Wireless</H3>"
				+ "Information about Bluetooth, 802.11, and more." + "</BODY>";
		
		String reg = "<[hH]([1-6])>.*</[hH]\\1>";

		Pattern patt = Pattern.compile(reg);
		Matcher mc = patt.matcher(s);
		
		
		System.out.println(s.replaceAll(reg, ",$0+++"));
		
		while (mc.find()) {
			System.out.println(mc.group().trim());
		}
		System.out.println("------------------------------");
		
		/**
		 * 输出: <H1>Welcome to my Homepage</H1> <H2>ColdFusion</H2>
		 */
		
		String ss="ABCDEFGHIJKL";
		String reg1 = "\\S{4}(?!$)";

		Pattern patt1 = Pattern.compile(reg1);
		Matcher mc1 = patt1.matcher(ss);

		while (mc1.find()) {
			System.out.println("Found value: " + mc1.group(0));
			System.out.println(mc1.group().trim());
		}
		
		
		System.out.println("------------------------------");
		
		String pattern1 = "\\d{4}(?!$)";

		String num1 = "1234567890";
		Pattern r1 = Pattern.compile(pattern1);
		Matcher m1 = r1.matcher(num1);
		
		StringBuilder res=new StringBuilder();
		/**
		 * 写成if了,还一直纳闷怎么就匹配不出来
		 */
		while (m1.find()) {
			System.out.println("Found value: " + m1.group(0));
			res.append(m1.group(0)+",");
			System.out.println(m1.group().trim());
			
		}
		System.out.println(res);
		
		/**
		 * 输出结果如下:
		 * 	Found value: ABCD
		 *	ABCD
		 *	Found value: EFGH
		 *	EFGH
		 *	Found value: 1234
		 *	1234
		 *	Found value: 5678
		 *	5678
		 *  1234,5678,
		 */
		
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值