Skip to content

Java正则表达式使用

小傅哥 edited this page May 20, 2020 · 1 revision

案例

//汉字范围u4E00-u9FA5
 
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class sxtRegex01 {
	
	public static void main(String[] args) {
		
		p("检查是否匹配:"+"abc".matches("..."));
		
		p("替换字符串:"+"abc123aa".replaceAll("\\d", "."));
		
		Pattern p = Pattern.compile("[a-z]{3}");
		Matcher m = p.matcher("fgha");
		p("Pattern+Matcher方法验证匹配:"+m.matches());
		
		p("------------------");
		
		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("R".matches("[A-Z&&(RFG)]"));
		
		p("------------------");
		
		p("a_8".matches("\\w{3}"));
		p("\\".matches("\\\\"));
		
		p("------------------");
		
		p("hello sir".matches("h.*"));
		p("hello sir".matches(".*ir$"));
		p("hello sir".matches("^h[a-z]{1,3}o\\b.*"));//匹配单词边界,单词边界是空格出现的位置用\\b匹配
		p("hellosir".matches("^h[a-z]{1,3}o\\b.*"));
		p(" \n".matches("^[\\s&&[^\\n]]*\\n$"));//开头是一个空格,且不能是换行符,最后必须是换行
	    
		p("------------------");
		
		Pattern p2 = Pattern.compile("\\d{3,5}");
		String s = "123-4536-89789-000";
		Matcher m2 = p2.matcher(s);
		
		p(m2.matches());
		m2.reset();//把吃进去的字符吐出来重新匹配,否经过m2.matches会吃进去字符 下面的匹配就不成功
		p(m2.find());
		p(m2.start()+"-"+m2.end());//找到了 就把首位位置打印下(必须找到才能打印)
		p(m2.find());
		p(m2.start()+"-"+m2.end());
		p(m2.find());
		p(m2.start()+"-"+m2.end());
		p(m2.find());
		
		p(m2.lookingAt());//每次都是才头上开始找
		
		p("------------------");
		
		Pattern p3 = Pattern.compile("java",Pattern.CASE_INSENSITIVE);//加属性后,Patter.CASE_INSENSITIVE表示大小写不管
		Matcher m3 = p3.matcher("java_Java_jAva_jAVa_IloveJava");
		p(m3.replaceAll("JAVA"));//把所有的都替换为大写的
		
		p("------------------按照单双数替换");
		Pattern p4 = Pattern.compile("java",Pattern.CASE_INSENSITIVE);//加属性后,Patter.CASE_INSENSITIVE表示大小写不管
		Matcher m4 = p4.matcher("java_Java_jAva_jAVa_IloveJava fdasfas");
		
		StringBuffer sb = new StringBuffer();
		int i = 0;
		while(m4.find()){
			i ++;
			if(i%2 == 0){
				m4.appendReplacement(sb, "java");
			}else{
				m4.appendReplacement(sb, "JAVA");
			}
		}
		m4.appendTail(sb);//把尾巴在再添加到buf上既是sb
		p(sb);
		
		p("------------------分组加括号只取数字一组");
		Pattern p5 = Pattern.compile("(\\d{3,5})([a-z]{2})");
		Matcher m5 = p5.matcher("123bb_78987dd_090po");
		
		while(m5.find()){
			p(m5.group(1));//grop括号里面第0组是整体,第一组是左起第一个括号,第二组是左起第二个括号
		}
		
		p("------------------贪婪的匹配与不贪婪匹配");
		Pattern p6 = Pattern.compile("(.{3,10}?)[0-9]");//.{3,10}后面没问号就是贪婪匹配会陪到最长,如果{3,10}?加?号就是懒蛋匹配之匹配最少的,从3个开始找
		Matcher m6 = p6.matcher("aaaa5dddd8");
		while(m6.find()){//如果这里用if(m6.find)(){p(m6.start()+"-"+m6.end());}  那么之匹配第一个
			p(m6.start()+"-"+m6.end());
		}
		
		p("------------------普通捕获");
		Pattern p7 = Pattern.compile(".{3}");
		Matcher m7 = p7.matcher("ab4dd5");
		while(m7.find()){
			p(m7.group());
		}
		
		p("------------------非捕获组");
		Pattern p8 = Pattern.compile(".{3}(?=a)");//(?=a)这个是非捕获组的意思,最后一个是a而且还不把这个a取出来!!(?=a)这个要是写在前面 就不一样了
		Matcher m8 = p8.matcher("ab4add5");
		while(m8.find()){
			p("后面不能是a的"+m8.group());
		}
		
		p8 = Pattern.compile("(?!a).{3}");//(?!a)前面不能是a的
		m8 = p8.matcher("abbsab89");
		while(m8.find()){
			p("前面不能是a的"+m8.group());
		}
		
		//(?<!a)从后往前数 不是a的
		//(?<=a)从后往前数 是a的
		p("------------------去除><号匹配");
		Pattern p9 = Pattern.compile("(?!>).+(?=<)");
		Matcher m9 = p9.matcher(">编程中国<");
		while(m9.find()){
			p(m9.group());
		}
		
		p("------------------向前引用");
		Pattern p10 = Pattern.compile("(\\d\\d)\\1");//这里面的1是向前引用,12是第一匹配到的,下一次在匹配出来12和前面相同 所以是true
		Matcher m10 = p10.matcher("1212");
		p(m10.matches());
		
		p("------------------忽略大小写,正则内嵌");//(?i)非捕获组里面这个表示忽略大小写
		p("java".matches("(?i)JAVA"));
	}
	
	public static void p(Object o){
		System.out.println(o);
	}
}

语法

字符 
x 字符 x 
\\ 反斜线字符 
\0n 带有八进制值 0 的字符 n (0 <= n <= 7) 
\0nn 带有八进制值 0 的字符 nn (0 <= n <= 7) 
\0mnn 带有八进制值 0 的字符 mnn0 <= m <= 30 <= n <= 7) 
\xhh 带有十六进制值 0x 的字符 hh 
\uhhhh 带有十六进制值 0x 的字符 hhhh 
\t 制表符 ('\u0009') 
\n 新行(换行)符 ('\u000A') 
\r 回车符 ('\u000D') 
\f 换页符 ('\u000C') 
\a 报警 (bell) 符 ('\u0007') 
\e 转义符 ('\u001B') 
\cx 对应于 x 的控制符 
  
字符类 
[abc] abc(简单类) 
[^abc] 任何字符,除了 abc(否定) 
[a-zA-Z] azAZ,两头的字母包括在内(范围) 
[a-d[m-p]] admp:[a-dm-p](并集) 
[a-z&&[def]] def(交集) 
[a-z&&[^bc]] az,除了 bc:[ad-z](减去) 
[a-z&&[^m-p]] az,而非 mp:[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] 
  
POSIX 字符类(仅 US-ASCII) 
\p{Lower} 小写字母字符:[a-z] 
\p{Upper} 大写字母字符:[A-Z] 
\p{ASCII} 所有 ASCII:[\x00-\x7F] 
\p{Alpha} 字母字符:[\p{Lower}\p{Upper}] 
\p{Digit} 十进制数字:[0-9] 
\p{Alnum} 字母数字字符:[\p{Alpha}\p{Digit}] 
\p{Punct} 标点符号:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ 
\p{Graph} 可见字符:[\p{Alnum}\p{Punct}] 
\p{Print} 可打印字符:[\p{Graph}\x20] 
\p{Blank} 空格或制表符:[ \t] 
\p{Cntrl} 控制字符:[\x00-\x1F\x7F] 
\p{XDigit} 十六进制数字:[0-9a-fA-F] 
\p{Space} 空白字符:[ \t\n\x0B\f\r] 
  
java.lang.Character 类(简单的 java 字符类型) 
\p{javaLowerCase} 等效于 java.lang.Character.isLowerCase() 
\p{javaUpperCase} 等效于 java.lang.Character.isUpperCase() 
\p{javaWhitespace} 等效于 java.lang.Character.isWhitespace() 
\p{javaMirrored} 等效于 java.lang.Character.isMirrored() 
  
Unicode 块和类别的类 
\p{InGreek} Greek 块(简单块)中的字符 
\p{Lu} 大写字母(简单类别) 
\p{Sc} 货币符号 
\P{InGreek} 所有字符,Greek 块中的除外(否定) 
[\p{L}&&[^\p{Lu}]]  所有字母,大写字母除外(减去) 
  
边界匹配器 
^ 行的开头 
$ 行的结尾 
\b 单词边界 
\B 非单词边界 
\A 输入的开头 
\G 上一个匹配的结尾 
\Z 输入的结尾,仅用于最后的结束符(如果有的话) 
\z 输入的结尾 
  
Greedy 数量词 
X? X,一次或一次也没有 
X* X,零次或多次 
X+ X,一次或多次 
X{n} X,恰好 n 次 
X{n,} X,至少 n 次 
X{n,m} X,至少 n 次,但是不超过 m 次 
  
Reluctant 数量词 
X?? X,一次或一次也没有 
X*? X,零次或多次 
X+? X,一次或多次 
X{n}? X,恰好 n 次 
X{n,}? X,至少 n 次 
X{n,m}? X,至少 n 次,但是不超过 m 次 
  
Possessive 数量词 
X?+ X,一次或一次也没有 
X*+ X,零次或多次 
X++ X,一次或多次 
X{n}+ X,恰好 n 次 
X{n,}+ X,至少 n 次 
X{n,m}+ X,至少 n 次,但是不超过 m 次 
  
Logical 运算符 
XY X 后跟 Y 
X|Y X 或 Y 
(X) X,作为捕获组 
  
Back 引用 
\n 任何匹配的 nth 捕获组 
  
引用 
\ Nothing,但是引用以下字符 
\Q Nothing,但是引用所有字符,直到 \E 
\E Nothing,但是结束从 \Q 开始的引用 
  
特殊构造(非捕获) 
(?: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,作为独立的非捕获组 

📝 首页

🌏 知识星球码农会锁

实战项目:「DDD+RPC分布式抽奖系统」、专属小册、问题解答、简历指导、架构图稿、视频课程

🐲 头条

⛳ 目录

  1. 源码 - :octocat: 公众号:bugstack虫洞栈 文章所涉及到的全部开源代码
  2. Java
  3. Spring
  4. 面向对象
  5. 中间件
  6. Netty 4.x
  7. 字节码编程
  8. 💯实战项目
  9. 部署 Dev-Ops
  10. 📚PDF 下载
  11. 关于

💋 精选

🐾 友链

建立本开源项目的初衷是基于个人学习与工作中对 Java 相关技术栈的总结记录,在这里也希望能帮助一些在学习 Java 过程中遇到问题的小伙伴,如果您需要转载本仓库的一些文章到自己的博客,请按照以下格式注明出处,谢谢合作。

作者:小傅哥
链接:https://bugstack.cn
来源:bugstack虫洞栈

2021年10月24日,小傅哥 的文章全部开源到代码库 CodeGuide 中,与同好同行,一起进步,共同维护。

这里我提供 3 种方式:

  1. 提出 Issue :在 Issue 中指出你觉得需要改进/完善的地方(能够独立解决的话,可以在提出 Issue 后再提交 PR )。
  2. 处理 Issue : 帮忙处理一些待处理的 Issue
  3. 提交 PR: 对于错别字/笔误这类问题可以直接提交PR,无需提交Issue 确认。

详细参考:CodeGuide 贡献指南 - 非常感谢你的支持,这里会留下你的足迹

  • 加群交流 本群的宗旨是给大家提供一个良好的技术学习交流平台,所以杜绝一切广告!由于微信群人满 100 之后无法加入,请扫描下方二维码先添加作者 “小傅哥” 微信(fustack),备注:加群。
微信:fustack

  • 公众号(bugstack虫洞栈) - 沉淀、分享、成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获。
公众号:bugstack虫洞栈

感谢以下人员对本仓库做出的贡献或者对小傅哥的赞赏,当然不仅仅只有这些贡献者,这里就不一一列举了。如果你希望被添加到这个名单中,并且提交过 Issue 或者 PR,请与我联系。

Clone this wiki locally