java 正则表达式详细

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

public class Test {

	public static void main(String[] args) {
		// 简单认识正则表达式的概念
		p("abc".matches("...")); // 一个.代表一个字符
		/*
		 * \d代表一位数字,用\\d是因为java有转义字符\"等,但是没有\d这种转义字符, 会报错,
		 * java看到\就会判断你是哪种转义字符,不是转义字符就会报错
		 */
		p("a789b".replaceAll("\\d", "-"));
		/*
		 * java.util.prefs.Pattern没有构造方法,
		 *  用它的静态的compile(String regex)方法,
		 * 代表把这种正则表达式编译一下,放入Pattern(模式)中,
		 *  首先编译好匹配效率高,每次重新编译效率底
		 */
		Pattern pa = Pattern.compile("[a-z]{3}"); // 三个字符,每个字符在a-z之间
		Matcher m = pa.matcher("abc");	//调用本方法去匹配某个字符串
		p(m.matches());	//调用本方法查看匹配的结果
		/*
		 * 这句话相当于上面的三句话,可是这句话执行的
		 * 时候还要先编译模式再执行,效率没有上面高
		 * 这句话也调用不到Pattern和Matcher的其他方法
		 */
		p("abc".matches("[a-z]{3}")); 
		
		/*
		 * .代表一个字符,*代表0个或多个字符,
		 * 也有正常的字符,比如模式中是aa,那么表示字母是aa的,
		 * 注意这里不是前两位是aa的,一定是多有位字母都一样,
		 * +代表一个或多个,?代表一个或0个
		 */
		
		p("a".matches("."));
		p("aaa".matches("aa"));	//和aaa匹配的是aaa不是aa,aa不代表aa开头
		p("aaaa".matches("a*"));
		p("aaaa".matches("a+"));
		p("".matches("a*"));
		p("".matches("a?"));
		p("aaaa".matches("a?"));	//和aaaa匹配的是aaaa不是a?,a?代表aa或""或a,并不是这个字符打头
		p("12156165156165".matches("\\d{3,100}"));
		p("192.168.0.1".matches("\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}"));	//{0,3}包含0和3
		p("192".matches("[0-2][0-9][0-9]"));	//[0-2]包含0和2
		
		
		/*
		 * 范围:
		 * [abdnsjbdbsa]代表的是匹配一个字符包含在[abdnsjbdbsa]之中,
		 * 一个[]代表匹配一个字符[a-zA-Z]表示这个字符在a-z和A-Z之间
		 * [a-zA-Z]这里zA中间不用加别的也可以写成[a-z]|[A-Z]还可以写成[a-z[A-Z]],
		 * [^abc]取反,除了abc的,[A-Z&&[ABC]]代表是A-Z之中的并且是ABC之间的
		 */
		p("a".matches("[abc]"));
		p("a".matches("[^abc]"));
		p("A".matches("[a-zA-Z]"));
		p("A".matches("[a-z]|[A-Z]"));
		p("A".matches("[a-z[A-Z]]"));
		p("N".matches("[A-Z&&[NMZ]]"));
		//这种方法去不到&&的取不到N!,目前只知道p("N".matches("[A-Z&&[NMZ]]"));这种方法
		p("N".matches("[A-Z]&&[NMZ]"));	
		
		/*
		 * 认识\s \w \d \
		 * 正则表达式本身也用\后边跟东西表示某些范围,
		 * 所以正则表达式中\用\\表示,
		 * 但是如果和java的\比较时,在"\\".matches("\\\\");
		 * 方法中"\\"代表了java的一个反斜线,
		 * 但是后面方法里要求传一个正则表达式模式的\,
		 * 但是正则表达式中用\\表示一个\,如果方法参数是\\的话,
		 * 在正则表达式中为\,传入方法后参数也就是\了,就报错了,
		 * 传入方法的应该是java中的\\,在正则表达式中就是\\\\,
		 * 这里是特别绕的
		 * \d	数字:[0-9]
		 * \D	非数字: [^0-9]
		 * \s	空白字符:[ \t\n\x0B\f\r]
		 * \S	非空白字符:[^\s]
		 * \w	单词字符:[a-zA-Z_0-9]
		 * \W	非单词字符:[^\w]
		 */
		p(" \n\r\t".matches("\\s{4}"));
		p(" ".matches("\\S"));
		p("a_8".matches("\\w{3}"));
		p("abc888&^%".matches("[a-z]{1,3}\\d{3}\\W{3}"));
		p("abc888&^%".matches("[a-z]{1,3}\\d+[&^#%]+"));
		p("\\".matches("\\\\"));
		
		//POSIX Style
		p("a".matches("\\p{Lower}"));
		
		//边界处理(开头结尾的处理)
		p("hello sir".matches("^h.*"));
		p("hello sir".matches(".*ir$"));
		p("hello sir".matches("^h[a-z]{1,3}o\\b.*"));
		p("hellosir".matches("^h[a-z]{1,3}o\\b*"));
		
		//找空白行
		p(" \n".matches("^[\\s&&[^\\n]]*\\n$"));
		
		//匹配Email
		p("123456789@qq.com".matches("[\\w[.-]]+@[\\w[.-]]+\\.[\\w[.-]]+"));
		
		/*
		 * matches find lookingAt
		 * matches永远是匹配整个字符串,但是matches方法匹配的时候,
		 * 比如匹配到第5个字符不匹配,就不会退回去了,
		 * 匹配位置就走到第5个了,find方法是匹配有没有子串,
		 * matches和find用时会有影响,调用reset方法把匹配位置重新弄到第一个,
		 * find一下就代表找一个字串,然后位置就到那,
		 * find第二次就接着从第一次往下的位置开始找,lookingAt方法也是找字串,
		 * 但是每次lookingAt都是从字符串开始处找
		 */
		Pattern p1 = Pattern.compile("\\d{3,5}");
		String s1 = "012-23561-265-00";
		Matcher m1 = p1.matcher(s1);
		p(m1.matches());
		m1.reset();
		p(m1.find());
		//返回找到的字串的起始位置和结束位置,start返回起始的位置,end返回结束的后一个位置
		p(m1.start() + "-" + m1.end()); 
		p(m1.find());
		//返回找到的字串的起始位置和结束位置,start返回起始的位置,end返回结束的后一个位置
		p(m1.start() + "-" + m1.end());
		p(m1.find());
		//返回找到的字串的起始位置和结束位置,start返回起始的位置,end返回结束的后一个位置
		p(m1.start() + "-" + m1.end()); 
		p(m1.find());
		//返回找到的字串的起始位置和结束位置,这里没找到会报错,用if判断上面的find方法
		//p(m1.start() + "-" + m1.end()); 
		p(m1.lookingAt());
		p(m1.lookingAt());
		p(m1.lookingAt());
		p(m1.lookingAt());
		
		/*
		 * replace
		 * 在调用Pattern.compile(String regex, int flags)方法时,
		 * 还可以指定一个匹配标志,这些标志是Pattern的静态常量,
		 * 然后循环调用Matcher对象的find方法可以找一个一个的字串,
		 * 接着调用Matcher对象的group()方法,可以返回由以前匹配操作
		 * 所匹配的输入子序列,调用replaceAll(String replacement)
		 * 方法可以替换模式(定义的模式)与给定替换字符串(模式检测的字符串)
		 * 相匹配的输入序列的每个子序列。
		 */
		Pattern p2 = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
		Matcher m2 = p2.matcher("java Java JAva JAVA IloveJAVa  asasas");
		/*
		 * 找是否有忽略大小的子串
		while(m2.find()) {
			p(m2.group());
		}
		*/
		//全部替换大写
		p(m2.replaceAll("JAVA"));
		/*
		 * 这里我想找到的单数用小写,找到的双数用大写
		 */
		StringBuffer sb = new StringBuffer();
		int index = 0;
		while(m2.find()) {
			index ++;
			if(index % 2 ==0) {
				//找到位置并替换放入StringBuffer中,前后不替换的字符串也会跟着加进去
				m2.appendReplacement(sb, "JAVA");	
			} else {
				m2.appendReplacement(sb, "java");
			}
		}
		/*
		 * 用来添加appendReplacement后剩余的字符串,
		 * 自己的程序中尚不需要(不知道怎么回事)
		 * m2.appendTail(sb);	
		 */
		p(sb);
		
		/*
		 * 正则表达式的匹配模式在定义的时候可以分组,分组用小括号来定义,
		 * 当小括号嵌套时,数左小括号,第几个就是第几组,
		 * 这样在找到这样模式的字串之后,就可以通过group(int 组号)
		 * 的方式取得当前组的值,传0或者调用重载的无参数的group方法就
		 * 是打印整个大组的值
		 */
		Pattern p3 = Pattern.compile("(\\d{3,5})([a-z]{2})");
		String s2 = "012aa-56565vv-3649rr-99";
		Matcher m3 = p3.matcher(s2);
		while(m3.find()) {
			p(m3.group(1));
		}
		
		/*
		 * qulifiers
		 * 这段程序Greedy("(.{3,10})[0-9]")在匹配的时候,
		 * 首先一看最多10个字符就直接吞进去10个字符,
		 * 然后和整个的正则表达式做匹配,发现如果只匹配(.{3,10})
		 * 后面还有个[0-9],这样不匹配,所以它吐出一个来,
		 * 然后再匹配,就匹配上了但是Reluctant("(.{3,10}?)[0-9]")
		 * 的在匹配的时候,吞最少的,首先吞进去三个,然后和整个模式匹配,
		 * 发现后面一位不是数字,再吞一个,发现匹配了,他就结束了,
		 * Possessive("(.{3,10}+)[0-9]")和Greedy差不多,都是吞最多的,
		 * 但是不吐,注意这里用了组是为的看的更清楚,
		 * 千万注意的是不要把Possessive("(.{3,10}+)[0-9]")和
		 * Greedy("(.+)[0-9]")混淆("(.{3,10}+)[0-9]")这个在Greedy
		 * 中是("(.{3,10})[0-9]")而("(.+)[0-9]")这个在Possessive中是
		 * ("(.++)[0-9]"
		 */
		Pattern p4 = Pattern.compile("(.{3,10})[0-9]");
		Matcher m4 = p4.matcher("aaaa5bbbb9");
		if(m4.find()) {
			p(m4.start() + "-" + m4.end());
		}else {
			p("没找到可以匹配的");
		}
		
		/*
		 * 特殊构造(非捕获)	这个要自己试,很绕很“诡异”
		 * (?:X)	X,作为非捕获组
		 * (?idmsux-idmsux) 	Nothing,但是将匹配标志i d m s u x on - off
		 * (?idmsux-idmsux:X)  	X,作为带有给定标志 i d m s u x on - off的非捕获组 
		 * (?=X)	X,通过零宽度的正 lookahead
		 * (?!X)	X,通过零宽度的负 lookahead
		 * (?<=X)	X,通过零宽度的正 lookbehind
		 * (?<!X)	X,通过零宽度的负 lookbehind
		 * (?>X)	X,作为独立的非捕获组
		 * 用的最多的是(?=X),加在后面不捕获,加在前面捕获
		 */
		Pattern p5 = Pattern.compile(".{3}(?=a)");
		String s5 = "123a46b";
		Matcher m5 = p5.matcher(s5);
		while(m5.find()) {
			p(m5.group());
		}
		
		/*
		 * 向前引用
		 * \\2的意思是我后面的数必须和第二组相同
		 *  \\1的意思是我后面的数必须和第一组相同
		 */
		Pattern p6 = Pattern.compile("(\\d(\\d))\\2");
		Matcher m6 = p6.matcher("122");
		p(m6.matches());
		
		/*
		 * flags的简写
		 * 打开静态常量可以找到简写形式
		 */
		Pattern p7 = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
		p("JAVa".matches("(?i)(java)"));
	}

	public static void p(Object o) { // 简化打印方法
		System.out.println(o);
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值