本章概述:
第一部分:正则表达式
第二部分:正则的方法和实现
第三部分:网页爬虫
第一部分:正则表达式
1、正则表达式:符合一定规则的表达式。
作用:用于专门操作字符串。
特点:用于一些特定的符号来表示一些代码操作。这样就简化书写。所以学习正则表达式,就是在学习一些特殊符号的使用。
好处:可以简化对字符串的复杂操作。
弊端:符号定义越多,正则越长,阅读性越差。
Regex
pattern 正则包装类
2、正则表达式的构造摘要:
字符
x 字符 x
\\ 反斜线字符
\t 制表符 ('\u0009')
\n 新行(换行)符 ('\u000A')
\r 回车符 ('\u000D')
\0n 带有八进制值 0 的字符 n (0 <= n <= 7)
\0nn 带有八进制值 0 的字符 nn (0 <= n <= 7)
\0mnn 带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7)
\xhh 带有十六进制值 0x 的字符 hh
\uhhhh 带有十六进制值 0x 的字符 hhhh
\f 换页符 ('\u000C')
\a 报警 (bell) 符 ('\u0007')
\e 转义符 ('\u001B')
\cx 对应于 x 的控制符
字符类
[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]
\w 单词字符:[a-zA-Z_0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\W 非单词字符:[^\w]
边界匹配器
^ 行的开头
$ 行的结尾
\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 次
3、反斜线、转义和引用
反斜线字符 ('\') 用于引用转义构造,如上表所定义的,同时还用于引用其他将被解释为非转义构造的字符。因此,表达式 \\ 与单个反斜线匹配,而 \{ 与左括号匹配。
在不表示转义构造的任何字母字符前使用反斜线都是错误的;它们是为将来扩展正则表达式语言保留的。可以在非字母字符前使用反斜线,不管该字符是否非转义构造的一部分。
4、具体操作功能:
1,匹配:String matches方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false。
2,切割:String split()方法,
3,替换:String replaceAll(regex,str);如果regex中有定义组,可以在第二参数中通过$符号获取正则表达式中的已有的组。符合一定规则的表达式
4,获取:将字符串中的符合规则的子串取出(参看网页爬虫)。
第二部分:正则的实现细节:
1、String中的正则应用:
方法:
(1)matches(Regex) 用正则表达式匹配字符串
(2)split(Regex) 用正则规则切割字符串成字符串数组
(3)replaceAll(regex,newstr) 用新的字符串替换符合规则的部分字符串
"(regex)\\1+","$1" 将叠词替换成单个词
组:"(regex)" 将括号中的规则封装成一个组,以便复用,每个组都有从1开始的自动编号,需要复用将编号转译就可以了
代码示例:
//正则操作字符串示例 class RegexDemo { public static void main(String[] args) { //调用匹配手机号的方法检查手机号是否匹配 System.out.println("匹配:"); String tel1 = "16811112222"; System.out.println("tel1:"+matche(tel1)); String tel2 = "15900001111"; System.out.println("tel2:"+matche(tel2)); System.out.println("切割:"); splitDemo("zhangsan.lisi.wangwu","\\."); //.在正则中属于有特殊意义的字符,需要将其转义成表示字符 splitDemo("c:\\abc\\a.txt","\\\\"); //“\\”表示转义后的“\”,所以“\\”需要转义两次 splitDemo("erkktyqqquizzzzzo","(.)\\1+");//按叠词切割。用“组”来复用规则 System.out.println("替换:"); String str = "gjkd13836543644000oiotrr12342223256mndd02034345675";//将字符串中的数组替换成#。 System.out.println(replaceAllDemo(str,"\\d{7,}","*")); String str1 = "WooooYYaaooXXXXXuueBBiaanCCCCCheng";//将叠词替换成单个词. System.out.println(replaceAllDemo(str1,"(.)\\1+","$1")); //用“$”获取前一个规则中的组 } /* 匹配手机号 号段只有 13xxx 15xxx 18xxxx */ public static boolean matche(String tel) { String telReg = "1[358]\\d{9}"; return tel.matches(telReg); //调用String中的字符串匹配方法匹配 } //用正则切割字符串 public static void splitDemo(String str,String reg) { String[] arr = str.split(reg); //String的切割方法 System.out.println("切割个数:"+arr.length); //遍历切割出来的字符 for(String s : arr) System.out.println(s); } //将str中符合reg正则的都替换成newStr public static String replaceAllDemo(String str,String reg,String newStr) { return str.replaceAll(reg,newStr); //String中的方法,符合正则的都替换成newStr } }
(4)获取:
将字符串中符合规则的子串取出
步骤
1,将正则表达式封装成对象。(Pattern)
2,让正则对象和要操作的字符串相关联。
3,关联后,获取正则匹配引擎。(Matcher)
4,通过引擎对符合规则的子串进行操作,比如取出
方法
Pattern compile(Regex) 该方法返回封装了正则的对象
Matcher matcher(str) 让正则对象和字符串相关联,获得匹配器对象
find 将规则作用在字符串上,并进行符合规则的子串查找
group 获取匹配后结果
start 获取匹配结果开始处的索引
end 获取匹配结果结尾处的索引
String中的matches方法就是用Pattern和Matcher对象实现的
思路:
(1)只想知道该字符串是否对错,使用匹配
(2)将已有字符串变成另一个字符串,使用替换
(3)按自己的方式将字符串变成多个字符串,使用切割,获取规则以外的子串
(4)想要拿到符合需求的字符串子串,获取,获取符合规则的子串
让正则对象和要操作的字符串相关联
关联后,获取正则匹配引擎
通过引擎对符合规则的子串进行操作,比如取出
练习:将IP地址进行地址段顺序的排序
思路:
用0补齐所有地址段到最长位
排序
除去前面的0
(都用replaceAll)
第三部分:网页爬虫
综合网络编程、IO流、正则表达式等知识点的应用
代码说明:
/* 需求:用网页爬虫在网络上扒出邮箱号 操作步骤: 1,连接网络资源,读取资源上的文本 2,用正则表达式的获取功能关联文本字符串 3,关联后,获取正则匹配引擎。 4,通过引擎将符合邮箱规则的子串取出 */ import java.io.*; import java.util.regex.*; import java.net.*; import java.util.*; class WebCrawler { public static void main(String[] args) throws Exception { //创建URL,写入网络资源路径 URL url = new URL("http://172.27.35.14:8080/myweb/mail.html"); //建立正则匹配规则 String mailReg = "\\w+@\\w+(\\.\\w+){1,3}"; //字母或数字@字母或数字(.字母或数字限制1到3次) //调用自定义方法,在网络中获取匹配规则的邮箱的列表 List<String> list = getElements(url,mailReg); //遍历列表 for (String s:list) { System.out.println(s); } } //获取网络上符合规则的字符串的列表 public static List<String> getElements(URL url,String reg)throws Exception { //创建URL连接,获取关联的流 URLConnection conn = url.openConnection(); BufferedReader bufIn = new BufferedReader(new InputStreamReader(conn.getInputStream())); //获取正则对象 Pattern p = Pattern.compile(reg); //new集合存放符合规则的字符串 ArrayList<String> list = new ArrayList<String>(); //在流中循环读取一行字符数据 String line = null; while((line=bufIn.readLine())!=null) { //将字符数据与正则对象关联,获取匹配引擎 Matcher m = p.matcher(line); //用匹配引擎的方法查找和获取符合规则的字符元素 while(m.find()) { list.add(m.group()); //返回此前匹配成功的字符元素,并添加到列表中 } } return list; //返回列表 } }
本章总结:
1、正则表达式是专门用于操作字符串的规则,由于开发中对字符串的操作非常频繁,所以专门定义出一个规则简化对字符串的操作步骤。
2、对字符串的操作有匹配、切割、替换和获取,需要熟悉正则表达式的构造规则,熟悉常用字符的含义,对组的复用要掌握。
3、正则表达式可以封装成对象Pattern,用它可以关联字符串获取匹配引擎Matcher,从而通过匹配引擎对符合规则的字符串进行操作,获取符合规则的字符串是比较常用的操作。
4、要在掌握知识的同时学会灵活应用,可以将各种学到的知识糅合到应用场景中,做到活学活用。