黑马程序员-Java基础-正则表达式

  

一、概述:

  正则表达式:符合一定规则的表达式。

  作用:用于专门操作字符串。可以简化对只付出的复杂操作。

  特点:用于一些特定的符号来表示一些代码操作。简化书写。

  弊端:符号定义越多,正则越长,阅读性越差。

  例如:对QQ号进行校验,要求5~15位,0不能开头,只能是数字。

  如果用String 类中的组合方法进行校验:

 1 //    String类中的方法组合:
 2     public static void checkQQ_1(String qq) {
 3         int len = qq.length() ;
 4         
 5         if (len > 15 || len < 5) {
 6             System.out.println("长度错误。");
 7         }
 8         else {
 9             if (qq.startsWith("0")){
10                 System.out.println("不能以0开头。");
11             }
12             else {
13                 
14                 try {
15                     long q = Long.parseLong(qq) ;
16                     System.out.println("qq:"+q);
17                 }
18                 catch(NumberFormatException e ) {
19                     System.out.println("出现非法字符。");
20                 }
21             }
22         }
23     }

  但是如果使用正则表达式:

 1 //    正则表达式:
 2     public static void checkQQ(String qq) {
 3 //        定义正则表达式规则:第一位是1-9中的一个,然后0-9中的数字出现4-14次。
 4         String regex = "[1-9][0-9]{4,14}" ;
 5         boolean flag = qq.matches(regex) ;
 6         if (flag)
 7             System.out.println(qq+":ok");
 8         else 
 9             System.out.println(qq+":不合法");
10     }

  总结:使用正则表达式操作字符串。可以简化对只付出的复杂操作。

二、常用正则表达式规则

  字符类 
  [abc] a、b 或 c(简单类) 

  [^abc] 任何字符,除了 a、b 或 c(否定) 

  [a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围)

  [a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集)

  [a-z&&[def]] d、e 或 f(交集)

  [a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](减去)

  [a-z&&[^m-p]] a 到 z,而非 m 到 p:[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] 
 
  Greedy 数量词
  X? X,一次或一次也没有
  X* X,零次或多次
  X+ X,一次或多次
  X{n} X,恰好 n 次
  X{n,} X,至少 n 次
  X{n,m} X,至少 n 次,但是不超过 m 次 
 
  边界匹配器
  ^ 行的开头
  $ 行的结尾
  \b 单词边界
  \B 非单词边界
  \A 输入的开头
  \G 上一个匹配的结尾 
  \Z 输入的结尾,仅用于最后的结束符(如果有的话) 

  \z 输入的结尾

三、正则表达式具体操作

  1、匹配: boolean matches(String regex)  用规则匹配整个字符串,只要有一处不符合规则就返回false。

  总结:如果只想知道该字符串是对是错,使用匹配。

  练习:匹配手机号码:通常手机号码是11位,而开头一般是13、15、18。

1 public static void checkPhone(){
2         String phone = "13821918343" ;
3         String regex = "1[358]\\d{9}" ;
4         System.out.println(phone.matches(regex));
5     }

  regex 的规则是:第一个数字为1,第二个数字是3、5和8中的其中一个,后面由9个0~9中的数字组成。

  

  2、切割: String[] split(String regex) ; 按照切割规则将字符串切割成多个子串。

  总结:想要按照自定的方式将字符串变成多个字符串,切割。获取规则以外的子串。

  

  3、替换:boolean replaceAll(String regex, String replacement) 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。

  总结:想要将已有的字符串变成另一个字符串,则使用替换。

  练习:将下列字符串转成:我要学编程。

   "我我我我...我要...要要要...学学..学编..编编编编编编编....编程.程...程程程..程"

  思路:先去掉".",然后将重叠字替换。

1     public static void test_1() {
2         String str = "我我我我...我要...要要要...学学..学编..编编编编编编编....编程.程...程程程..程" ;
3 //        将正则表达式封装成对象:
4         String regex_1 = "\\.+" ;
5         String regex_2 = "(.)\\1+" ;
6         String str_r = str.replaceAll(regex_1, "") ;
7         System.out.println(str_r);
8         System.out.println(str_r.replaceAll(regex_2, "$1")); 
9     }

  总结:“(.)” 表示将任意字符封装成组,“\1”表示取第1组。“$1”,也是相当于取第一组的意思。

  

  4、获取:将字符串中符合规则的子串取出 

  步骤:
       1、将正则表达式封装成对象。Pattern p = Pattern.complite(regex) ;
       2、让正则对象和要操作的字符串相关联,获取正则匹配引擎。Matcher m = p.matcher(string) ;
       3、通过引擎对符合规则的子串进行操作。

四、练习

  练习:将IP地址进行地址段顺序的排序。 192.223.1.234 102.49.23.13 10.10.10.10 1.1.1.1 8.109.90.30

  思路:按照字符串的顺序排序。但是前提是要让它们每一位都是3位。则是在前面补0。

  1、按照每一段需要的最多的0进行补齐,所以每一位至少有3位。

  2、然后将每一段只保留3位。

  3、切割出每一个IP地址,去掉0开头。

 1 public static void test_1() {
 2         String str = "192.223.1.234 102.49.23.13 10.10.10.10 1.1.1.1 8.109.90.30" ;
 3 //        补齐:最多补2个0;
 4         str = str.replaceAll("(\\d+)", "00$1");
 5         System.out.println("补0后:"+str);
 6 //        每一段只保留3位;
 7         str = str.replaceAll("0*(\\d{3})", "$1") ;
 8         System.out.println("去0后:"+str);
 9 //        切割
10         String[] ips = str.split(" ") ;
11 //        排序
12         TreeSet<String> ipSet = new TreeSet<String>() ; 
13         
14         for(String ip : ips) {
15             ipSet.add(ip) ; 
16         }
17 //        去掉开头的0;
18         for(String ip : ipSet) {
19             System.out.println(ip.replaceAll("0*(\\d+)", "$1"));
20         }
21     }

  

  练习:网页爬虫:获取网页上的邮箱。

  即按照自己的规则,去获取网页上面的数据:网页爬虫。

  获取邮箱则要定义邮箱的正则表达式:

  较为精确的匹配:\w+@[\w&&[^_]]+(\.[a-zA-z]+)+

  相对不太精确的匹配:\w+@\w+(\.\w+)+

 1 import java.net.*; 
 2 import java.util.regex.*;
 3 import java.io.*;
 4 public class RegexTest2 {
 5     public static void main(String[] args)throws Exception {
 6         getEmail() ;
 7     }
 8     public static void getEmail() throws Exception {
 9         URL url = new URL("http://tieba.baidu.com/p/2358578408") ;
10         URLConnection conn = url.openConnection() ;
11         BufferedReader bufr = 
12             new BufferedReader(new InputStreamReader(conn.getInputStream())) ; 
13 //        定义正则规则,将正则表达式封装成对象。
14         String regex = "\\w+@[\\w&&[^_]]+(\\.[a-zA-z]+)+" ;
15         Pattern p = Pattern.compile(regex) ; 
16         
17         String line = null ; 
18         while((line=bufr.readLine())!=null) {
19             Matcher m = p.matcher(line) ; 
20             while(m.find()) {
21                 System.out.println(m.group());
22             }
23         }
24     }
25 }

  总结:Matcher 类中封装了许多对匹配字符的操作。

  

posted @ 2013-05-30 10:35  贺佐安  阅读(775)  评论(0编辑  收藏  举报