正则表达式

来源:互联网 发布:阿里云tv遥控器 编辑:程序博客网 时间:2024/05/17 01:46

//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 也可以是正常字符  truep("aaaaa".matches("a*")); // * 表示0个或多个  truep("".matches("a*")); //   truep("b".matches("a*")); //   falsep("a".matches("a+")); // + 表示1个或多个  truep("".matches("a+")); //  falsep("".matches("a?")); // ? 表示1个或0个  truep("a".matches("a?"));  //truep("aa".matches("a?")); //falsep("aa".matches("a{2}")); // {n}  正好n个  truep("aaa".matches("a{2}")); //falsep("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}")); //truep("aaa".matches("a{2,4}")); //truep("aaaa".matches("a{2,4}")); //truep("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到Zp("a".matches("[a-z[A-Z]]")); //a到z或者A到Zp("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]  falsep("d".matches("\\D")); //truep(" ".matches("\\s")); // \s 空格 [\t\n\x0B\f\r]  \S 非空格   truep("sdd".matches("[\\w]{3}")); // \w [a-zA-Z_0-9]  truep("sdd".matches("[a-zA-Z_0-9]{3}")); // \w [a-zA-Z_0-9]  truep("\\".matches("\\\\"));  //java中 一个\ 要和它后边的字符构成转义字符 ,所以要表示一个\ ,就要用\\来表示  true//正则表达式要表示一个\ ,需要用2个\\来表示,要表示2个\\,所以需要用4个\来表示

//边界p("hello sir".matches("^h.*")); //^在[]里面[^]表示取反,在[]外则表示一行的开始  truep("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() 匹配整个字符串  falsem.reset(); // 执行matches()后,“匹配器”会吃进几个字符,当遇到不符合pattern的字符时就停下来,reset()即将吃进的吐出来,恢复到初始状态p(m.find()); // find() 在字串中找是否有符合pattern的    truep(m.start()+"-"+m.end()); //start() 被找见的子串的开始的位置,end() 结束的位置p(m.find());// truep(m.start()+"-"+m.end());p(m.find());// falsep(m.lookingAt()); //总是从头开始匹配 falsep(m.lookingAt()); // falsep(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(".")); // 只有一个.表示一个任意字符truep("a".matches(".")); // truep("ab".matches(".")); // falsep("ab".matches(".*")); // truep(".".matches("\\.")); // 要表示就是一个. 而不代表任意字符 在.前加\\ truep("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("^\\*\\..*")); //以*. 开头的字符串 falsep("*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 ,能多不少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

// non-capturing groupPattern p = Pattern.compile(".{3}(?=a)"); //以a结束,前面有三个字符String input = "444a66b";Matcher m = p.matcher(input);while(m.find())p(m.group()); //444// non-capturing groupPattern 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中的一个  truep("3".matches("35|50")); //falsep("35".matches("[35|50]")); // 3,5,0的一个 ,和[350]效果一样  falsep("35".matches("[350]")); //   falsep("3".matches("[350]")); //   true//下面的正则表示的是135,50,86加8个数字的 中的一个Pattern p = Pattern.compile("^135|50|86\\d{8}");p(p.matcher("13593250698").matches()); //falsep(p.matcher("135").matches()); //truep(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")); // falsep("1".matches("\\d"));// truep("11".matches("\\d"));// false//非负整数p("0".matches("\\d+"));// true//正整数p("0".matches("[\\d&&[^0]]\\d*"));// falsep("20".matches("[\\d&&[^0]]\\d*"));// truep("20".matches("(\\d&&[^0])\\d*"));// []表示范围,()表示分组,似乎&&只用在[]中  falsep("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]+")); //falsep("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边界 boundryPattern p = Pattern.compile("\\bhi\\b.*\\bLucy\\b",Pattern.CASE_INSENSITIVE);String s = "hi,this is him,he always says 'Hi,\r\nLucy,How are you'";String s1 = "hi,this is him,he always says 'Hi,Lucy,How are you'";Matcher m = p.matcher(s);Matcher m1 = p.matcher(s1);p(m.find()); //falsep(m1.find()); //true

//找出以g开头的单词(不区分大小写)Pattern p = Pattern.compile("\\bg\\w*\\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()); //goodxxdPattern p = Pattern.compile("g.*d",Pattern.CASE_INSENSITIVE);String s = "he said this is good,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("\\(?0\\d{2}\\)?[) -]?\\d{8}");    String s1="010)-12345678";    Matcher m0 = p.matcher(s1);    p(m0.matches()); //true        //用分枝条件解决这个问题    Pattern p2 = Pattern.compile("\\(0\\d{2}\\)\\d{8}|0\\d{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]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)"); String ip = "0.25.139.195";  //true String ip2 = "256.300.888.999"; //false  //表示0-199的数 Pattern p = Pattern.compile("[01]?\\d\\d?"); 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()); //truep(p.matcher("<a>").matches()); //false //后向引用//用于重复搜索前面某个分组匹配的文本。例如,\1代表分组1匹配的文本 (不用后向引用,还真不好表示重复啊!)// () 表示分组,以(为基准,第一个(为组1,第二个(为组2Pattern p2 = Pattern.compile("\\b(\\w+)\\b\\s+\\1\\b");Pattern p2 = Pattern.compile("\\b(?<gw>\\w+)\\b\\s+\\k<gw>\\b"); //自定义组名 (?<name>exp) 或者 (?'name'exp),后向引用 \k<name>p(p2.matcher("aa aa").matches()); //truep(p2.matcher("1 1").matches()); //truep(p2.matcher("11 21").matches()); //false

//零宽断言 // (?=exp) 断言自身出现的位置的后面能匹配表达式expPattern p = Pattern.compile("\\b\\w+(?=ing\\b)"); //以ing结尾的单词的前面的部分,即不包含ing//Pattern p = Pattern.compile("\\b\\w+(?=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) 断言自身出现的位置的前面能匹配表达式expPattern p = Pattern.compile("(?<=\\bre)\\w+\\b"); //以re开头的单词的后面的部分,即不包含reString 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,890static 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的单词。  “\\b\\w*q[^u]\\w*\\b” 当q位于开头及中间时是正确的,当q位于末尾时就出错了p("qty".matches("\\b\\w*q[^u]\\w*\\b")); //true p("query".matches("\\b\\w*q[^u]\\w*\\b")); //falsep("Iraq fighting".matches("\\b\\w*q[^u]\\w*\\b")); //true q[^u] 要匹配后面不是u的字符,就把空格算作那个字符p("Iraq fighting".matches("\\b\\w*q(?!u)\\w*\\b")); //false 负向零宽断言 它只匹配一个位置,并不消费任何字符//匹配不包含连续字符串abc的单词p("dabcd".matches("\\b((?!abc)\\w)+\\b")); //false p("dbcd".matches("\\b((?!abc)\\w)+\\b")); //truep("abcd".matches("\\b((?!abc)\\w)+\\b")); //falsep("dabc".matches("\\b((?!abc)\\w)+\\b")); //false ,(?!abc)\\w 这个不是应该表示\w之前不是连续字符abc的吗,之后的也能表示的了?//前面不是小写字母的七位数字p("a1234567".matches("(?<![a-z])\\d{7}"));//falsep("01234567".matches("(?<![a-z])\\d{7}"));//falsep("1234567".matches("(?<![a-z])\\d{7}"));//truep("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]?\\d\\d?(?#0-199)");//贪婪 ,尽可能多的匹配//懒惰,尽可能少的匹配, 在贪婪的限定符后加 ? // *?,+?,??,{n,m}?,{n,}?


看完了马士兵老师讲的正则表达式,感觉上掌握了有60%的东西,剩下的还需要以后实际使用中再体会和总结。

通过不断练习感觉掌握程度达到了70%。


0 0
原创粉丝点击