正则表达式
发布时间:2020-12-13 23:11:40 所属栏目:百科 来源:网络整理
导读://greedy quantifiers,能多不少Pattern p = Pattern.compile(".{2,5}d");String input = "aa3bb4c";Matcher m = p.matcher(input);if(m.find())p(m.group()); //结果:aa3bb4//reluctant quantifiers,能少不多Pattern p = Pattern.compile(".{2,5}?d");S
//greedy quantifiers,能多不少 Pattern p = Pattern.compile(".{2,5}d"); String input = "aa3bb4c"; Matcher m = p.matcher(input); if(m.find()) p(m.group()); //结果:aa3bb4 //reluctant quantifiers,能少不多 Pattern p = Pattern.compile(".{2,5}?d"); String input = "aa3bb4c"; Matcher m = p.matcher(input); if(m.find()) p(m.group()); //结果:aa3 //Possessive quantifiers,这个比较特别 Pattern p = Pattern.compile(".{2,5}+d"); String input = "aa3"; Matcher m = p.matcher(input); if(m.find()) p(m.group()); //结果:空 Pattern p = Pattern.compile(".{2,5}+d"); String input = "aa3bbb4"; Matcher m = p.matcher(input); if(m.find()) p(m.group()); //结果:a3bbb4 一个字符串将其中的数字换成“-”,一般的做法是比较每个char然后再替换
String s = "ad233dd"; StringBuffer sb = new StringBuffer(); sb.append(s); for(int i=0;i<s.length();i++){ if((int)s.charAt(i) >= 48 && (int)s.charAt(i) <=57){ sb.replace(i,i+1,"-"); } } s = sb.toString(); 但用正则表达式,一句话就搞定
String s = "ad233dd"; s = s.replaceAll("d","-");(java中反斜杠和它后边的字符组合在一起表示“转义”字符)
Pattern p = Pattern.compile("[a-z]{3}"); //compile 目的是为了匹配起来更快 Matcher m = p.matcher("abc"); boolean b = m.matches(); "abc".matches("[a-z]{3}"); //这一句话效果上和上面三句是一样的,但上面的也有其优点 static void p(Object o){ System.out.println(o); } p("aa".matches("aa")); //regex 也可以是正常字符 true p("aaaaa".matches("a*")); // * 表示0个或多个 true p("".matches("a*")); // true p("b".matches("a*")); // false p("a".matches("a+")); // + 表示1个或多个 true p("".matches("a+")); // false p("".matches("a?")); // ? 表示1个或0个 true p("a".matches("a?")); //true p("aa".matches("a?")); //false p("aa".matches("a{2}")); // {n} 正好n个 true p("aaa".matches("a{2}")); //false p("a".matches("a{2,}")); // false x{n,} 最少n个 p("aaa".matches("a{2,}")); // true p("a".matches("a{2,4}")); // false x{n,m} 最少n个 最多m个 p("aa".matches("a{2,4}")); //true p("aaa".matches("a{2,4}")); //true p("aaaa".matches("a{2,4}")); //true p("aaaaa".matches("a{2,4}")); //false //范围 p("a".matches("[a-d]")); //a到d中的一个 p("a".matches("[b-f]")); p("a".matches("[^abc]")); //非abc中的任何字符 p("a".matches("[a-zA-Z]")); //a到z或者A到Z p("a".matches("[a-z[A-Z]]")); //a到z或者A到Z p("d".matches("[a-z&&[def]]")); //def中的一个 p("b".matches("[a-z&&[^bcd]]")); //a到z中不是bcd的字符 p("a".matches("[a-z&&[^bcd]]")); //认识 . /s /S /d /D /w /W / p("234".matches("[d]{1,2}")); // d [0-9]0到9的数字 D [^0-9] false p("d".matches("D")); //true p(" ".matches("s")); // s 空格 [tnx0Bfr] S 非空格 true p("sdd".matches("[w]{3}")); // w [a-zA-Z_0-9] true p("sdd".matches("[a-zA-Z_0-9]{3}")); // w [a-zA-Z_0-9] true p("".matches("\")); //java中 一个 要和它后边的字符构成转义字符 ,所以要表示一个,就要用来表示 true //正则表达式要表示一个,需要用2个来表示,要表示2个,所以需要用4个来表示 //边界 p("hello sir".matches("^h.*")); //^在[]里面[^]表示取反,在[]外则表示一行的开始 true p("hello sir".matches(".*ir$")); // $ 一行的结尾 true,注意是“行”以ir结尾的,如果改成“hello siraaa”则为false,^ 行的开始,$行的结尾 p(" n".matches("^[s&&[^n]]*n$")); //一个或多个空白字符,然后换行 true
// matches reset find lookingAt 使用 Pattern p = Pattern.compile("d{3,5}"); String s = "23-22222-33-777"; Matcher m = p.matcher(s); p(m.matches()); //matches() 匹配整个字符串 false m.reset(); // 执行matches()后,“匹配器”会吃进几个字符,当遇到不符合pattern的字符时就停下来,reset()即将吃进的吐出来,恢复到初始状态 p(m.find()); // find() 在字串中找是否有符合pattern的 true p(m.start()+"-"+m.end()); //start() 被找见的子串的开始的位置,end() 结束的位置 p(m.find());// true p(m.start()+"-"+m.end()); p(m.find());// false p(m.lookingAt()); //总是从头开始匹配 false p(m.lookingAt()); // false p(m.lookingAt());// false //Matcher 用法 group() replaceAll() Pattern p = Pattern.compile("java",Pattern.CASE_INSENSITIVE); String s = "java Java JaVa ilovejaVA aaa"; Matcher m = p.matcher(s); while(m.find()) p(m.group()); //group() 结果等同于s.subString(m.start(),m.end()) p(m.replaceAll("*")); //replaceAll() 替换所有找到的字串为* //Matcher 奇数的java替换成* 偶数的替换成- Pattern p = Pattern.compile("java",Pattern.CASE_INSENSITIVE); String s = "bbjavac Javac JaVa ilovejaVA aaa"; Matcher m = p.matcher(s); StringBuffer sb = new StringBuffer(); int i = 0; while(m.find()){ //find() appendReplacement() appendTail() 一般组合使用 i++; if(i%2 == 0){ m.appendReplacement(sb,"-"); }else{ m.appendReplacement(sb,"*"); } p(m.start()+"-"+m.end()); p("i="+i+","+sb); } m.appendTail(sb); p(sb); //取出匹配p的字串中的数字 Pattern p = Pattern.compile("d{3,5}[a-zA-Z]{2}"); String s = "234aab =55555ccll*222cc*"; Matcher m = p.matcher(s); Pattern p2 = Pattern.compile("d{3,5}"); while(m.find()){ String ss = m.group(); Matcher m2 = p2.matcher(ss); while(m2.find()) //再循环去取 p(m2.group()); } //取出匹配p的字串中的数字 用()分组 Pattern p = Pattern.compile("(d{3,5})([a-zA-Z]{2})"); //第一个左(所在组的组id是1,以此类推 String s = "234aab =55555ccll*222cc*"; Matcher m = p.matcher(s); while(m.find()){ p(m.group(1)); //本身符合p的字串是一个组group(0),group(1)是第一个()组,group(2)是第二个()组 } // . . 的使用 p(".".matches(".")); // 只有一个.表示一个任意字符 true p("a".matches(".")); // true p("ab".matches(".")); // false p("ab".matches(".*")); // true p(".".matches(".")); // 要表示就是一个. 而不代表任意字符 在.前加 true p("a".matches(".")); // 要表示就是一个. 而不代表任意字符 在.前加 false //邮件地址爬虫 static void getEmailAdd() throws IOException{ File f = new File("d://email.txt"); BufferedReader br = new BufferedReader(new FileReader(f)); String temp = null; while((temp = br.readLine()) != null){ parse(temp); } br.close(); } private static void parse(String temp) { Pattern p = Pattern.compile("[w-[^s]]+@[w[^s]]+.[w[^s]]+",Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(temp); while(m.find()) p(m.group()); }
p("*ss".matches("^*..*")); //以*. 开头的字符串 false p("*ss".matches("^[*.].*")); //以*. 中的任意一个开头的字符串 true //统计代码中的空行,注释行,代码行 static void statisticCodeLines() throws IOException{ File f = new File("d://src"); File[] fs = f.listFiles(); Map<String,Integer> map = new HashMap<String,Integer>(); for(File child : fs){ if(child.getName().matches(".*.java$")){ //统计 后缀是.java的文件,也可以用 endWith() parse(child,map); } } Set<String> keys = map.keySet(); Iterator<String> it = keys.iterator(); while(it.hasNext()){ String next = it.next(); p(next+":"+map.get(next)); } } private static void parse(File child,Map<String,Integer> map) throws IOException { BufferedReader br = new BufferedReader(new FileReader(child)); String temp = null; while((temp = br.readLine()) != null){ //readLine() 返回的String中已经将换行符给去掉,只包含内容 temp = temp.trim(); //trim() 将开头与结尾的空白字符去掉 if(temp.matches("[s&&[^n]]*")){ //空行 if(null == map.get("空行")){ map.put("空行",1); }else{ map.put("空行",map.get("空行") + 1); } }else if(temp.matches("^//.*") || temp.matches("^/*.*") || temp.matches("^*.*")){ //注释行 //else if(temp.matches("^//.*") || temp.startsWith("/*") || temp.startsWith("*")){ // startWith() 也可以 if(null == map.get("注释行")){ map.put("注释行",1); }else{ map.put("注释行",map.get("注释行") + 1); } }else{ //代码行 if(null == map.get("代码行")){ map.put("代码行",1); }else{ map.put("代码行",map.get("代码行") + 1); } } } } //greedy quantifiers,5}+d");
String input = "aa3bbb4";
Matcher m = p.matcher(input);
if(m.find())
p(m.group()); //结果:a3bbb4
// non-capturing group Pattern p = Pattern.compile(".{3}(?=a)"); //以a结束,前面有三个字符 String input = "444a66b"; Matcher m = p.matcher(input); while(m.find()) p(m.group()); //444 // non-capturing group Pattern p = Pattern.compile("(?=a).{3}"); //以a打头,包含a在内有3个字符 String input = "444a66b"; Matcher m = p.matcher(input); while(m.find()) p(m.group()); //a66
//表示某几个数字中的一个 p("35".matches("35|50")); //35,50中的一个 true p("3".matches("35|50")); //false p("35".matches("[35|50]")); // 3,5,0的一个 ,和[350]效果一样 false p("35".matches("[350]")); // false p("3".matches("[350]")); // true //下面的正则表示的是135,50,86加8个数字的 中的一个 Pattern p = Pattern.compile("^135|50|86d{8}"); p(p.matcher("13593250698").matches()); //false p(p.matcher("135").matches()); //true p(p.matcher("50").matches()); //true //135,150,186段的电话号码 Pattern p = Pattern.compile("^1(35|50|86)d{8}"); String s = "18893254998"; Matcher m = p.matcher(s); p(m.matches()); // d 表示的是 0-9的数字,等于[0-9] p("-1".matches("d")); // false p("1".matches("d"));// true p("11".matches("d"));// false //非负整数 p("0".matches("d+"));// true //正整数 p("0".matches("[d&&[^0]]d*"));// false p("20".matches("[d&&[^0]]d*"));// true p("20".matches("(d&&[^0])d*"));// []表示范围,()表示分组,似乎&&只用在[]中 false p("20".matches("[1-9]d*"));// true //非正整数 p("-980".matches("0|^-d+")); p("哈".matches("[u4e00-u9fa5]")); //true 匹配中文字符 p("哈看的哈".matches("[u4e00-u9fa5]+")); //true 匹配中文字符串 p("哈看的哈dd".matches("[u4e00-u9fa5]+")); //false p("10000".matches("[1-9]d{4,}")); //true 匹配腾讯QQ号,从10000开始,最少5位 p("1000099".matches("[1-9]d{4,}")); //true p("1".matches("d{,3}")); //报错 ! p("1".matches("d{0,3}")); //true 最多3位 //将字符串中的钱数找出来 Pattern p = Pattern.compile("(d+.?d*)元"); String s = "23元坎坎坷坷88看看66.23元"; Matcher m = p.matcher(s); while(m.find()) p(m.group(1)); //BufferedReader 的 readLine() 方法会把换行符去掉 //A String containing the contents of the line,not including any line-termination characters,//or null if the end of the stream has been reached // "." 表示除换行符外的任意字符 ,b word边界 boundry Pattern p = Pattern.compile("bhib.*bLucyb",Pattern.CASE_INSENSITIVE); String s = "hi,this is him,he always says 'Hi,rnLucy,How are you'"; String s1 = "hi,Lucy,How are you'"; Matcher m = p.matcher(s); Matcher m1 = p.matcher(s1); p(m.find()); //false p(m1.find()); //true //找出以g开头的单词(不区分大小写) Pattern p = Pattern.compile("bgw*b",Pattern.CASE_INSENSITIVE); String s = "he said this is good,but GoodMan didn't think so"; Matcher m = p.matcher(s); while(m.find()) p(m.group()); // ^g.*d$ 表示整行或整个字符串要以g开头,d结尾,中间包含任意个不是换行符的字符 // g.*d 表示字符串中包含g打头d结尾的字符串 Pattern p = Pattern.compile("^g.*d$",Pattern.CASE_INSENSITIVE); String s = "gooxxd"; Matcher m = p.matcher(s); while(m.find()) p(m.group()); //goodxxd Pattern p = Pattern.compile("g.*d",but GoooooodMan didn't think so"; Matcher m = p.matcher(s); while(m.find()) p(m.group()); // good,but GoooooodMan did // 要表示正则中的元字符,比如:.、*、(等,需要转义 p(".hha ss*".matches("^..**$")); //true 表示以.开头,以*结尾,中间是除换行外的任意字符 p(".hha ss".matches("^..**$")); //false //分枝条件 正则表达式里的分枝条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开 //这个可以表示(010)12345678 010-12345678 010 12345678 3位区号加8位的电话号码, //但也可以表示这种 010)-12345678 不正确的电话格式 Pattern p = Pattern.compile("(?0d{2})?[) -]?d{8}"); String s1="010)-12345678"; Matcher m0 = p.matcher(s1); p(m0.matches()); //true //用分枝条件解决这个问题 Pattern p2 = Pattern.compile("(0d{2})d{8}|0d{2}[- ]?d{8}"); String s2="011 12345678"; String s3="011-12345678"; Matcher m1 = p2.matcher(s1); Matcher m2 = p2.matcher(s2); Matcher m3 = p2.matcher(s3); p(m1.matches()); //false p(m2.matches());//true p(m3.matches());//true //分组,重复单个字符直接在单个字符后面加上限定符就可以,如果要重复多个字符可以用分组,()后加上限定符。而且分组的功能不限于此 //匹配ip地址 Pattern p2 = Pattern.compile("((2[0-4]d|25[0-5]|[01]?dd?).){3}(2[0-4]d|25[0-5]|[01]?dd?)"); String ip = "0.25.139.195"; //true String ip2 = "256.300.888.999"; //false //表示0-199的数 Pattern p = Pattern.compile("[01]?dd?"); p(p.matcher("0").matches()); p(p.matcher("3").matches()); p(p.matcher("99").matches()); p(p.matcher("199").matches()); p(p.matcher("200").matches()); //false //反义 //表达不属于某个能简单定义的字符类的字符 // W 不是字母数字下划线,S 不是空白字符,B 不是单词开头结束的位置 ,D 不是数字 ,[^a] 除a外的任意字符,[^aeiou] 除aeiou外的任意字符 Pattern p = Pattern.compile("<a[^>]+>"); //用尖括号括起来的以a开头的字符串 p(p.matcher("<aa>").matches()); //true p(p.matcher("<a>").matches()); //false //后向引用 //用于重复搜索前面某个分组匹配的文本。例如,1代表分组1匹配的文本 (不用后向引用,还真不好表示重复啊!) // () 表示分组,以(为基准,第一个(为组1,第二个(为组2 Pattern p2 = Pattern.compile("b(w+)bs+1b"); Pattern p2 = Pattern.compile("b(?<gw>w+)bs+k<gw>b"); //自定义组名 (?<name>exp) 或者 (?'name'exp),后向引用 k<name> p(p2.matcher("aa aa").matches()); //true p(p2.matcher("1 1").matches()); //true p(p2.matcher("11 21").matches()); //false //零宽断言 // (?=exp) 断言自身出现的位置的后面能匹配表达式exp Pattern p = Pattern.compile("bw+(?=ingb)"); //以ing结尾的单词的前面的部分,即不包含ing // Pattern p = Pattern.compile("bw+(?=ing)b"); //为什么这个不可以呢,和上面的区别在哪里? String s = "I'm singing while you're dancing"; Matcher m = p.matcher(s); while(m.find()) p(m.group()); //sing danc // (?<=exp) 断言自身出现的位置的前面能匹配表达式exp Pattern p = Pattern.compile("(?<=bre)w+b"); //以re开头的单词的后面的部分,即不包含re String s = "I'm readding a book"; Matcher m = p.matcher(s); while(m.find()) p(m.group()); // adding // 给一个很长的数字中每三位间加一个逗号 StringBuffer sb = new StringBuffer(); String s = "1234567890"; String r = dealNumber(s,new StringBuffer()).toString(); p(r); // 1,234,567,890 static StringBuffer dealNumber(String s,StringBuffer sb){ Pattern p = Pattern.compile("((?<=d)d{3})+b"); //3位,3位 从右往左数 Matcher m = p.matcher(s); if(m.find()){ sb.append(s.substring(0,m.start())+","); dealNumber(m.group(),sb); } else{ sb.append(s); } return sb; } //负向零宽断言 // (?!exp) 断言此位置后面不能匹配表达式exp (?<!exp) 断言此位置前面不能匹配表达式exp //要查找字母q后面不是u的单词。 “bw*q[^u]w*b” 当q位于开头及中间时是正确的,当q位于末尾时就出错了 p("qty".matches("bw*q[^u]w*b")); //true p("query".matches("bw*q[^u]w*b")); //false p("Iraq fighting".matches("bw*q[^u]w*b")); //true q[^u] 要匹配后面不是u的字符,就把空格算作那个字符 p("Iraq fighting".matches("bw*q(?!u)w*b")); //false 负向零宽断言 它只匹配一个位置,并不消费任何字符 //匹配不包含连续字符串abc的单词 p("dabcd".matches("b((?!abc)w)+b")); //false p("dbcd".matches("b((?!abc)w)+b")); //true p("abcd".matches("b((?!abc)w)+b")); //false p("dabc".matches("b((?!abc)w)+b")); //false,(?!abc)w 这个不是应该表示w之前不是连续字符abc的吗,之后的也能表示的了? //前面不是小写字母的七位数字 p("a1234567".matches("(?<![a-z])d{7}"));//false p("01234567".matches("(?<![a-z])d{7}"));//false p("1234567".matches("(?<![a-z])d{7}"));//true p("A1234567".matches("(?<![a-z])d{7}"));// 应该是true才对呀,为什么是false呢? //不包含属性的简单HTML标签内里的内容 //(?<=<(w{0,"+(Integer.MAX_VALUE-1)+"})>) 被尖括号括起来的单词 // 对 / 转义,1 反向引用组1的内容 //捕获的是<b></b>之间的内容 ,不包括前缀和后缀本身 Pattern p = Pattern.compile("(?<=<(w{0,"+(Integer.MAX_VALUE-1)+"})>).*(?=</1>)"); String s = "<b>haha</b>"; Matcher m = p.matcher(s); while(m.find()) p(m.group()); //haha //注释 (?#comment) Pattern p = Pattern.compile("2[0-4]d(?#200-249)|25[0-5](?#250-255)|[01]?dd?(?#0-199)"); //贪婪 ,尽可能多的匹配 //懒惰,尽可能少的匹配,在贪婪的限定符后加 ? // *?,+?,??,{n,m}?,}? 看完了马士兵老师讲的正则表达式,感觉上掌握了有60%的东西,剩下的还需要以后实际使用中再体会和总结。 通过不断练习感觉掌握程度达到了70%。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |