正则表达式的构造摘要
构造 | 匹配 |
| |
字符 | |
x | 字符 x |
\\ | 反斜线字符 |
\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 |
\t | 制表符 ('\u0009') |
\n | 新行(换行)符 ('\u000A') |
\r | 回车符 ('\u000D') |
\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] |
\s | 空白字符:[ \t\n\x0B\f\r] |
\S | 非空白字符:[^\s] |
\w | 单词字符:[a-zA-Z_0-9] |
\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 次 |
Logical 运算符 | |
XY | X 后跟 Y |
X|Y | X 或 Y |
(X) | X,作为捕获组 |
组和捕获
捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:
1 | ((A)(B(C))) |
2 | \A |
3 | (B(C)) |
4 | (C) |
组零始终代表整个表达式。
之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。捕获的子序列稍后可以通过 Back 引用在表达式中使用,也可以在匹配操作完成后从匹配器获取。
与组关联的捕获输入始终是与组最近匹配的子序列。如果由于量化的缘故再次计算了组,则在第二次计算失败时将保留其以前捕获的值(如果有的话)例如,将字符串 "aba" 与表达式 (a(b)?)+ 相匹配,会将第二组设置为 "b"。在每个匹配的开头,所有捕获的输入都会被丢弃。
以 (?) 开头的组是纯的非捕获 组,它不捕获文本,也不针对组合计进行计数。
正则表达式:
正确的规则
* 正则表达式。
*
* 正则表达式用于操作字符串数据。
* 通过一些特定的符号来体现的。
* 所以我们为了掌握正则表达式,必须要学习一些符号。
*
* 虽然简化了,但是阅读性差。
/*
* 正则表达式对字符串的常见操作:
* 1, 匹配。
* 其实使用的就是String类中的matches()方法。
* 2,切割。
* 其实使用的就是String类中的split()方法。
* 3,替换。
* 其实使用的就是String类中的replaceAll()方法。
* 4,获取。
*/
练习1:
/*
* 需求:定义一个功能对QQ号进行校验。
* 要求:长度5~15. 只能是数字, 0不能开头
*/
String regex = "[1-9][0-9]{4,14}";//正则表达式。
练习2:
1 public static void functionDemo_1(){ 2 //匹配手机号码是否正确。 3 String tel = "15800001111"; 4 String regex = "1[358]\\d{9}"; 5 boolean b = tel.matches(regex); 6 System.out.println(tel+":"+b); 7 }
\\ 反斜线字符
\d 数字:[0-9]
X{n,m} X,至少 n 次,但是不超过 m 次
X{n} X,恰好 n 次
练习3:
/*
* 切割。
* 组:((A)(B(C)))
*/
1 public static void functionDemo_2(){ 2 String str = "zhangsanttttxiaoqiangmmmmmmzhaoliu"; 3 4 String[] names = str.split("(.)\\1+");//str.split("\\."); 5 6 for(String name : names){ 7 System.out.println(name); 8 } 9 }
想把t,m都切割出去。现象是后一位和前一位都一样,而且字母不确定。“.“是代表任意字符。下一位要和上一位内容一样,意味着第一位的内容在被复用。怎么实现复用呢?java当中复用是封装成函数,正则当中复用直接用小括号就可以了”(.)”,函数封装还有个名字,正则封装后只要有小括号就自动编号,从1开始,再写一个2编号。这就叫做“组”。第二个和第一个一样就用组,用编号代表组。写1的话是普通的1,所以要用组标号用转义字符来表示“\\1”, (.)\\1 出现至少一次再用一个“+”符号。整个就是"(.)\\1+"
输出:
zhangsan
xiaoqiang
zhaoliu
练习4:
/*
* 替换
*/
1 public static void functionDemo_3() { 2 String str = "zhangsanttttxiaoqiangmmmmmmzhaoliu"; 3 str = str.replaceAll("(.)\\1+", "$1"); 4 System.out.println(str); 5 String tel = "15800001111";//158****1111; 6 tel = tel.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"); 7 System.out.println(tel); 8 }
想把字符串中连续的多个t和多个m变成一个t和一个m,怎么办?
如果想在一个方法里,第一个参数带正则的话,第二个参数想使用第一个参数正则中的内容,可以用“$”符号来表示,叫做获取前一个参数中的第一组。
158****1111 这种形式的电话号码分为三部分,
\\d{3}\\d{4}\\d{4}这个地方不用再去管前三个数的特点了因为这个地方不对前三个数字操作。
再按照组的特点,给前三个和后四个划分到组中,分别是组1和组2,对应后边参数的$1,$2,第二个参数引用到第一个参数中的组。
输出:
zhangsantxiaoqiangmzhaoliu
158****1111
练习5:
/*
* 获取
* 将正则规则进行对象的封装。
* Pattern p = Pattern.compile("a*b");
* //通过正则对象的matcher方法字符串相关联。获取要对字符串操作的匹配器对象Matcher .
* Matcher m = p.matcher("aaaaab");
* //通过Matcher匹配器对象的方法对字符串进行操作。
* boolean b = m.matches();
*/
1 public static void functionDemo_4() { 2 String str = "da jia hao,ming tian bu fang jia!"; 3 String regex = "\\b[a-z]{3}\\b"; 4 //1,将正则封装成对象。 5 Pattern p = Pattern.compile(regex); 6 //2, 通过正则对象获取匹配器对象。 7 Matcher m = p.matcher(str); 8 //使用Matcher对象的方法对字符串进行操作。 9 //既然要获取三个字母组成的单词 10 //查找。 find(); 11 System.out.println(str); 12 while(m.find()){ 13 System.out.println(m.group());//获取匹配的子序列 14 System.out.println(m.start()+":"+m.end()); 15 } 16 }
输出:
da jia hao,ming tian bu fang jia!
jia
3:6
hao
7:10
jia
29:32
练习:
1 public class RegexTest { 2 public static void main(String[] args) { 3 /* 4 * 1,治疗口吃:我我...我我...我我我要...要要要要...要要要要..学学学学学...学学编编...编编编编..编..程程...程程...程程程 5 * 2,对ip地址排序。 6 * 3,对邮件地址校验。 7 */ 8 test_3(); 9 } 10 //对邮件地址校验。 11 public static void test_3() { 12 String mail = "abc1@sina.com.cn"; 13 String regex = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]{1,3})+"; 14 regex = "\\w+@\\w+(\\.\\w+)+";//1@1.1 15 boolean b = mail.matches(regex); 16 System.out.println(mail+":"+b); 17 } 18 /* 19 * 1,治口吃。 20 */ 21 public static void test_1(){ 22 String str = "我我...我我...我我我要...要要要要...要要要要..学学学学学...学学编编...编编编编..编..程程...程程...程程程"; 23 //1,将字符串中.去掉。 用替换。 24 str = str.replaceAll("\\.+", ""); 25 System.out.println(str); 26 //2,替换叠词。 27 str = str.replaceAll("(.)\\1+", "$1"); 28 System.out.println(str); 29 } 30 /* 31 * ip地址排序。 32 * 192.168.10.34 127.0.0.1 3.3.3.3 105.70.11.55 33 */ 34 public static void test_2(){ 35 String ip_str = "192.168.10.34 127.0.0.1 3.3.3.3 105.70.11.55"; 36 //1,为了让ip可以按照字符串顺序比较,只要让ip的每一段的位数相同。 37 //所以,补零,按照每一位所需做多0进行补充。每一段都加两个0. 38 ip_str = ip_str.replaceAll("(\\d+)", "00$1"); 39 System.out.println(ip_str); 40 //然后每一段保留数字3位。 41 ip_str = ip_str.replaceAll("0*(\\d{3})", "$1"); 42 System.out.println(ip_str); 43 //1,将ip地址切出。 44 String[] ips = ip_str.split(" +"); 45 TreeSet<String> ts = new TreeSet<String>(); 46 for(String ip : ips){ 47 // System.out.println(ip); 48 ts.add(ip); 49 } 50 for(String ip : ts){ 51 System.out.println(ip.replaceAll("0*(\\d+)", "$1")); 52 } 53 } 54 }
网络爬虫:
1 /* 2 * 网页爬虫:其实就一个程序用于在互联网中获取符合指定规则的数据。 3 * 爬取邮箱地址。 4 */ 5 public class RegexTest2 { 6 public static void main(String[] args) throws IOException { 7 List<String> list = getMailsByWeb(); 8 for(String mail : list){ 9 System.out.println(mail); 10 } 11 } 12 public static List<String> getMailsByWeb() throws IOException { 13 //1,读取源文件。 14 // BufferedReader bufr = new BufferedReader(new FileReader("c:\\mail.html")); 15 URL url = new URL("http://192.168.1.100:8080/myweb/mail.html"); 16 17 BufferedReader bufIn = new BufferedReader(new InputStreamReader(url.openStream())); 18 //2,对读取的数据进行规则的匹配。从中获取符合规则的数据. 19 String mail_regex = "\\w+@\\w+(\\.\\w+)+"; 20 List<String> list = new ArrayList<String>(); 21 Pattern p = Pattern.compile(mail_regex); 22 String line = null; 23 while((line=bufIn.readLine())!=null){ 24 Matcher m = p.matcher(line); 25 while(m.find()){ 26 //3,将符合规则的数据存储到集合中。 27 list.add(m.group()); 28 } 29 } 30 return list; 31 } 32 public static List<String> getMails() throws IOException{ 33 //1,读取源文件。 34 BufferedReader bufr = new BufferedReader(new FileReader("c:\\mail.html")); 35 //2,对读取的数据进行规则的匹配。从中获取符合规则的数据. 36 String mail_regex = "\\w+@\\w+(\\.\\w+)+"; 37 38 List<String> list = new ArrayList<String>(); 39 40 Pattern p = Pattern.compile(mail_regex); 41 42 String line = null; 43 while((line=bufr.readLine())!=null){ 44 45 Matcher m = p.matcher(line); 46 while(m.find()){ 47 //3,将符合规则的数据存储到集合中。 48 list.add(m.group()); 49 } 50 } 51 return list; 52 } 53 }