java正则表达式
一、正则表达式基本规则
1 package org.mytest; 2 3 4 import java.util.Arrays; 5 //java.util.regex正则表达式工具包 6 import java.util.Random; 7 import java.util.regex.Matcher; 8 import java.util.regex.Pattern; 9 10 11 12 public class Test { 13 14 15 //正则表达式就是字符串, java用regex标识 16 //字符串的 matches方法可以接收正则表达式 17 public static void test1() { 18 19 //正则表达式就是字符串 20 //字符串的 matches方法可以接收正则表达式 21 // 案例1 22 //3个字 23 System.out.println("三个字案例"); 24 String str = "1234"; 25 String str2 = "...";//.在正则表达式的规范就是任意一个字符 26 System.out.println(str.matches(str2)); 27 System.out.println("123".matches(str2)); 28 29 30 System.out.println("手机号案例"); 31 //案例2 32 //判断是否是手机号 33 //定义字符串匹配规则 34 // String pattern = "1[3,5,8]\\d{9}";//[]里面不要乱添加,分割符。错误 35 String pattern = "1[358]\\d{9}";//正确 36 // String pattern = "1[358][1-9]{9}";//另外的正确写法 37 System.out.println("1,382557144".matches(pattern));//false,如果pattern[]里面有空格就是true 38 System.out.println("12346578987".matches(pattern));//true 39 40 System.out.println("汉字案例"); 41 //案例3 42 //判断字符串中有没有汉字 43 // 以\开始的字符就是转义字符。\u是字符的另一种十六进制写法,是Unicode字符集,可以表示所有世界各国文字 "\u9fa5" 是java的Unicode 转义字符,后面跟4位16进制数,表示一个4位16进制的一个整数 44 //0x4e00 - 0x9fa5 就是汉字的值的范围。 编码格式 unicode(不要研究) 45 // pattern = "[\u4e00-\u9fa5]*";//全是中文吗? 空字符也算。若有字符必须是中文。 46 // pattern = ".*[\u4e00-\u9fa5].*";//有中文就行 47 // pattern = "[\u4e00-\u9fa5]]{1,}";//全是中文,不能为空 48 pattern = "[\u4e00-\u9fa5]]+";//全是中文,不能为空 49 50 System.out.println("hello中国!".matches(pattern)); 51 System.out.println("你好".matches(pattern)); 52 System.out.println("".matches(pattern)); 53 //案例4 54 //要求账号的姓名要么全中文,要么全英文,不能有其它特殊符号 55 String name = "张三李四王五"; 56 name = name.trim();//清除两边空格 57 58 if(name.matches("[\u4e00-\u9fa5]{2,6}|[a-zA-Z]{2,20}")){//方式1,正则表达式可以有逻辑运算|或者 59 //还是不要随意添加空格。没有分割符 60 //作用是:两边的正则表达式满足其一就行 61 // if(name.matches("[\u4e00-\u9fa5]{2,6}")||name.matches("[a-zA-Z]{1,20}")){//方式2 62 System.out.println("命名正确"); 63 } 64 else{ 65 System.out.println("命名错误"); 66 } 67 68 //总结 69 //1、不要随意添加分隔字符,每一个字符都是有用的。 70 //2、 正则表达式有逻辑或运算 71 //详细规则如下: 72 System.out.println("单个字符练习案例"); 73 74 //非运算 75 //不是A, 76 pattern = "[^A]"; 77 // pattern = "^A";pattern = "^[A]";//^表示开始,正好意义相反了 78 System.out.println("a".matches(pattern)); 79 System.out.println("A".matches(pattern)); 80 //不是[A-Z] 81 pattern = "[^A-Z]"; 82 System.out.println("T".matches(pattern)); 83 System.out.println("t".matches(pattern)); 84 //^ -运算符需要写到里面 85 //^最后运算 86 87 //或者运算符 88 //a-z或者A-Z 89 //方式一 90 pattern = "[a-zA-Z]"; 91 System.out.println("m".matches(pattern)); 92 System.out.println("M".matches(pattern)); 93 System.out.println("0".matches(pattern)); 94 //方式二 95 pattern = "[a-z]|[A-Z]"; 96 System.out.println("m".matches(pattern)); 97 System.out.println("M".matches(pattern)); 98 System.out.println("0".matches(pattern)); 99 100 //java中的转义字符练习 101 //表示空格--java里面 \s就是空格space 102 pattern = "\s"; 103 104 System.out.println(" ".matches(pattern)); 105 System.out.println("java中\\s到底是什么:你好啊\s张三"); 106 // "\s"就是一个空格的字符串 107 108 109 //1、总结正则表达式需要首先遵守java语言的字符串规范。 110 //1.转义字符会自动转义--java字符串规范 111 //2.最终的结果遵守正则表达式规范 112 // 正则表达式也有自己的转义字符,同样用\作为开始 113 //总而言之,正则表达式要用转义字符,必须写两个\\,一个不够 114 //验证1 115 // System.out.println("\w");//java中的非法转义符 116 pattern = "\\w";//java中表示字符串 \w 正则表达式中表示表示任意的一位字母或数字 117 System.out.println("1".matches(pattern));//true 118 System.out.println("a".matches(pattern));//true 119 System.out.println("A".matches(pattern));//true 120 System.out.println("".matches(pattern));//false 121 122 pattern = "\\s";//java中表示字符串 \s 正则表达式该字符串表示一位空格 123 System.out.println(" ".matches(pattern));//true 124 System.out.println("a".matches(pattern));//false 125 126 //验证2 正则表达式转义字符的大写就是逻辑非 127 System.out.println("z".matches("\\S"));//true 128 System.out.println(" ".matches("\\D"));//true 129 130 System.out.println("多个字符练习案例"); 131 //练习多个字符串 132 //每个字符都是a-z, *就是任意个数的意思 133 pattern = "[a-z]*"; 134 //不能为空,+就是至少一个的意思等同于{1,} 135 pattern = "[a-z]+"; 136 //0个或1个小写字母 137 pattern = "[a-z]?"; 138 // pattern构造是私有的 ,我们不能new,别人帮我们new 139 //{}表示个数的意思, 140 pattern = "[a-z]{10}"; 141 //,分割上下界 相当于+ 142 pattern = "[a-z]{1,}"; 143 //字符个数闭区间[1,10] 144 pattern = "[a-z]{1,10}"; 145 146 //总结 147 //3.不存在二义性,运行可能出现异常,因为不符合定义规范。 148 149 //[]{}里面参数不能为空 150 //正则表达式在遵守java字符串规则后,发现不遵守自己的规则,于是出现异常。 151 //异常1 java.util.regex.PatternSyntaxException 152 // pattern = "[a-z]{}"; 153 // System.out.println("a{}".matches(pattern)); 154 155 //异常2 java.util.regex.PatternSyntaxException 156 // pattern = "[]"; 157 // System.out.println("[]".matches(pattern)); 158 //异常原因:因为若[]里面是空的,[]代表[]里面的任意一个字符,这没有啊,{}里面是空的,个数没法确定了。 159 //异常3 java.util.regex.PatternSyntaxExceptio 160 // pattern = "\\"; 161 // System.out.println("\\".matches(pattern)); 162 //异常原因:符合java字符串语法要求,但是不符合正则表达式语法要求。没法转移啊,类似异常1,和异常2 163 164 165 //最后正则表达式的开始和结束标识^和$练习 166 167 System.out.println("liu".matches("^liu"));//true --自动跳过了开始标识^ 168 System.out.println("liu".matches("liu$"));//true --自动跳过了结束标识$ 169 System.out.println("liu".matches("^liu$"));//true --自动跳过了开始和结束标识 170 System.out.println("liu".matches("liu"));//true--不添加也可 171 System.out.println(); 172 //开始和结束标识说明了是正则表达式,不是普通字符串,这点在java中没有体现。 173 //没有必要,因为java自动认定为正则表达式,正则表达式大部分情况下兼容字符串。 174 // 下面是不兼容的一个情况。 175 //如果开始或结束标识不在相应位置,那么是错误的正则表达式。 176 pattern = "l^i$u"; 177 pattern = "^l^i$u$";//我就算加了开始和结束也是不正确的,匹配不到 178 // pattern = "^l\\^i\\$u$";//这样写,下面的"l^i$u"情况是对的。想要开始和结束出现中间,必须转义 179 180 System.out.println("i".matches(pattern));//false 181 System.out.println("l^i$u".matches(pattern));//false 182 183 System.out.println("l".matches(pattern));//false 184 System.out.println("u".matches(pattern));//false 185 System.out.println("li".matches(pattern));//false 186 System.out.println("iu".matches(pattern));//false 187 System.out.println("liu".matches(pattern));//false 188 189 System.out.println("l^iu".matches(pattern));//false 190 System.out.println("li&u".matches(pattern));//false 191 System.out.println("l^i&u".matches(pattern));//false 192 193 System.out.println("^liu".matches(pattern));//false 194 System.out.println("liu&".matches(pattern));//false 195 System.out.println("^liu&".matches(pattern));//false 196 197 System.out.println("^l^i&u&".matches(pattern));//false 198 System.out.println("^l^iu&".matches(pattern));//false 199 System.out.println("^l^i&u&".matches(pattern));//false 200 201 System.out.println("正则表达式训练结束"); 202 System.out.println("使用正则表达式开始:"); 203 //案例一 204 //将字符串分割成多个字符串。 205 //"java,php,mysql,javascript,c/c++"可以通过字符串split操作分割成多个字符串数组。 206 String str1 = "java,php,mysql,javascript,c/c++"; 207 String[] ch = str1.split(","); 208 System.out.println(Arrays.toString(ch)); 209 210 //那么 "java123php456mysql789javascript567c/c++"怎么分割 211 str1 = "java123php456mysql789javascript567c/c++";//[java, php, mysql, javascript, c/c++] 212 213 214 //字符串split方法可以接收正则表达式作为分隔符。 215 //那么要注意普通字符串和正则表达式不能冲突的问题。这不是我们考虑的,用就行了。 216 217 // ch = str1.split("//d+");//低级错误,//不是转义字符 218 ch = str1.split("\\d+");//错误了因为不是转义字符 219 220 System.out.println(Arrays.toString(ch));//[java, php, mysql, javascript, c/c++] 221 222 //理解贪婪模式 223 //分组非常妙 -- 反向理解 ->正向理解 224 //换名 225 //找所有的合适的字符串 226 //把他人的项目作者改为自己 227 228 //什么是贪婪模式-- 229 //在字符匹配的时候 230 //我想要 (zhangsan)(java)(lisi) 加括号是为了分组,更加清晰 231 232 //我这样写正则表达式 233 pattern = ".*java.*"; 234 str1 = "zhangsanjavalisi"; 235 str2 = "http:127.0.0.0:8080/www.taobao.ui.zhangsanjavalisi.com"; 236 System.out.println(str1.matches(pattern)); 237 System.out.println(str2.matches(pattern)); 238 } 239 240 241 242 243 public static void main(String[] args){ 244 test(); 245 } 246 247 //深入理解正则表达式 248 //java.util.regex包主要包含以下三个类 249 //Pattern类:模式类, 250 //ma 匹配器类 251 252 253 public static void test(){ 254 255 Pattern p = Pattern.compile("\\d?");//模式类,返回是一个Pattern 256 //私有的,其它任何人都不能new,类可以new。 257 Matcher m = p.matcher("a"); 258 System.out.println(m.matches());//false 259 System.out.println(m.find());//true 260 261 //把姓李的人的名字列出来 262 String str = """ 263 李四,java 264 1234王五1234,李武,李留 265 ,李六七八九sir 266 """; 267 // p = Pattern.compile("李.{1,2}");//错误 名字应该是中文 268 // p = Pattern.compile("李[\u4e00-\u9fa5]*");//错误 性李的名字长度应该2-3 269 p = Pattern.compile("李[\u4e00-\u9fa5]{1,2}");//正确 270 271 m = p.matcher(str); 272 //输出所有姓李的人 ,类似集合遍历 273 //find()作用 274 // 一方面是看看有没有元素, 275 // 另一方面后移一位元素,方便group()方法使用。 276 //group()作用 277 //返回当前匹配的结果, 278 while(m.find()){ 279 System.out.print(m.group()+" ");//输出结果 :李四 李武 李留 李六七 280 } 281 //这个答案,李六七算是半对。可以认为这是名字,也可以认为不是。 282 283 //1-9要求 按顺序数字顺序写成一个式子 284 // 如 1+23-45+67+8-9 285 // 使得结果为 100 286 287 //方法1 288 //如果告诉你一个式子,让你计算怎么办 289 str = "1+23-4+56-89"; 290 //正解: 291 //使用正则表达式,1.分割整数,2为整数添加符号 292 //使用 Matcher 遍历 拿到所有符合的字符串 293 p = Pattern.compile("-?\\d+"); 294 295 m = p.matcher(str); 296 297 while (m.find()){ 298 System.out.print(m.group()+" ");//1 23 -4 56 -89 299 //这样就有符号了 ,可以将String变为Integer 300 } 301 302 //剩下问题就是构造,str 303 //Str是随机的,比较简单,但是会重复 304 //Str按照顺序来, 305 // 1-9,正负号 306 Random random = new Random(); 307 //我想着用StringBuilder添加随机的数据 308 // char[] ch = new char[] {' ','-','+'};//错误 ,只能1位一位的 309 String[] ch = new String[] {"","-","+"};//需要空字符,用于连接两个数字 310 311 int sum; 312 while(true){ 313 sum = 0; 314 //生成一个字符串。 315 // StringBuilder sb = new StringBuilder(); 316 StringBuilder sb = new StringBuilder("1");//需要从1开始 317 for(int i=2; i<=9; i++){ 318 //随机 319 // sb.append(ch[random.nextInt(3)]); 320 // sb.append(('0'+i)); 321 sb.append(String.format("%s%d",ch[random.nextInt(3)],i)); 322 } 323 //构造输出str 324 str = sb.toString(); 325 p = Pattern.compile("-?\\d+");//自动把+去掉了,但是不影响符号 326 m = p.matcher(str); 327 while (m.find()){ 328 sum += Integer.parseInt(m.group()); 329 } 330 if(sum==100){ 331 System.out.println(str); 332 break; 333 } 334 } 335 } 336 }
二、 正则表达式贪婪模式和分组
1 package before; 2 //练习贪婪模式 3 4 import java.util.regex.Matcher; 5 import java.util.regex.Pattern; 6 7 public class Test { 8 //什么是贪婪模式 9 //1.在正则表达式字符个数是一定范围时,默认按最多匹配原则, 10 //也就是,如果范围是[1,10]。10个字符匹配的就按10个,10个不匹配,按9个....最后才按1个 11 //这用现象叫做贪婪模式 12 //禁用贪婪 13 //1.在正则表达式字符个数一定范围时,默认按最少匹配原则, 14 public static void test1(){ 15 //不贪婪,只有一个,或者最多一个 16 System.out.println("java123mysql6php".replaceAll(".*","-")); 17 //"--" 18 System.out.println("java123mysql6php".replaceAll("","-")); 19 //-j-a-v-a-1-2-3-m-y-s-q-l-6-p-h-p- 20 System.out.println("java123mysql6php".replaceAll(".*?","-")); 21 System.out.println("java123mysql6php".replaceAll("\\d+?","-")); 22 System.out.println("java123mysql6php".replaceAll("\\d","-")); 23 System.out.println("java123mysql6php".replaceAll("\\d{1,}?","-")); 24 //-j-a-v-a-1-2-3-m-y-s-q-l-6-p-h-p- 25 System.out.println("java123mysql6php".replaceAll("\\d+","-")); 26 /* 27 java---mysql-php 28 java---mysql-php 29 java---mysql-php 30 java-mysql-php 31 * */ 32 } 33 34 //案例一:打印出<div>标签有java</div> 35 //易错点,模式匹配 36 //关闭贪婪模式 37 //贪婪模式结论 38 //找到的字符串一定符合Pattern模式要求 39 //1、没有公共部分,不能往回找. 40 //2、符合正则表达式的要求 41 //3、字符串匹配顺序为:从前往后,不论是否关闭贪婪,都是这个顺序, 42 //4、关闭贪婪就是在{1,n}范围尽可能少的找,贪婪模式尽可能多的找 43 44 public static void test2(){ 45 String str = """ 46 <div>hello</div><div> java15 </div><div><p> java 15</p><span> java8 </p><div> java 15</div></div> 47 """; 48 Pattern p = Pattern.compile("(<div>[^<]*?)(java)([^>]*?</div>)");//规定了不选什么 49 // Pattern p = Pattern.compile("<div>[\\w ]*?java[\\w ]*?</div>");//规定了选哪些值 50 //其它错误 51 // Pattern p = Pattern.compile("<div>.*?java</div>"); 52 //无 53 //[ ] 54 55 // Pattern p = Pattern.compile("<div>(.{0,5}?)(java).*?</div>");//深刻理解控制区间。 56 // Pattern p = Pattern.compile("<div>(.*?)(java).*?</div>"); 57 //结果 58 //<div>hello</div><div>java15</div> 59 //<div><p>java 15</p><span>java8</p><div>java 15</div> 60 // Pattern p = Pattern.compile("<div>java.*?</div>"); 61 //<div>java15</div> 62 //<div>java 15</div> 63 // Pattern p = Pattern.compile("<div>[\\w ]+?java[\\w ]+?</div>");//{1,} {0,1}有区别 64 //无 65 // Pattern p = Pattern.compile("<div>[\\w ]*?(java)[\\w ]*?</div>");//可以添加括号 66 //<div>java15</div> 67 //<div>java 15</div> 68 /* 69 * <div>hello</div><div>java 15</div> 70 <div><p>java 15</p><span>java8</p><div>java 15</div> 71 */ 72 Matcher m = p.matcher(str); 73 while(m.find()){ 74 System.out.println(m.group()); 75 } 76 } 77 78 //()括号,分组 79 //1.有利于模式匹配;更加清晰.容易理解 80 //2.有利于结果操作;可以批量修改.方便修改, 81 public static void test3(){ 82 String str = """ 83 <div>hello</div><div> java15 </div><div><p> java 15</p><span> java8 </p><div> java 15</div></div> 84 """; 85 //只将<div>标签中的java替换为abc 86 87 Pattern p = Pattern.compile("(<div>[^<]*?)(java)([^>]*?</div>)"); 88 Matcher m = p.matcher(str); 89 //替换原来的字符串,返回字符串。 90 String t = m.replaceAll("$1abc$3"); 91 System.out.println(t); 92 } 93 94 public static void main(String[] args) { 95 test2(); 96 } 97 }
1.能用普通字符串解决的不用正则表达式。
2022/9/17
正则表达式运算符使用
1.字符串startWith不支持正则表达式
12356开头或者 12456开头可以这样写
1 String pattern = "12(3|4)56.*"; 2 System.out.println("123565464".matches(pattern));