正则表达式:符合一定规则的表达式
作用:用于专门操作字符串
虽然String类中有很多方法也可以实现,但是过于复杂
规则:
字符 | |
---|---|
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] |
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 | 输入的结尾 |
上面的只是列举了常用的规则,想了解全部规则,可以参考我另外一篇博客(java中Pattern类)http://blog.csdn.net/manfulleo/article/details/51114353
关于java正则表达式Pattern类中Greedy,Rsluctant,Possessive的区别,可以参考luoweifu的博客 http://blog.csdn.net/luoweifu/article/details/42759439
1.匹配
boolean | matches(String regex) 告知此字符串是否匹配给定的正则表达式。 |
import java.util.regex.*;
public class Demo{
public static void main(String[] args) {
//第一种方法
Pattern p = Pattern.compile(".*foo");
String str1 = "xfooxxxxxxfoo";
Matcher m = p.matcher(str1);
boolean b = m.matches();
System.out.println(b);
//第二种方法
String regex = ".*foo";
String str2 = "xfooxxxxxxfoo";
System.out.println(str2.matches(regex));
checkQQ();
checkTel();
}
//检测QQ格式
//5-15位,只有数字,第一位不可以为0
static void checkQQ(){
String qq = "123a15a";
String regex = "[1-9]\\d{4,19}";
boolean flag = qq.matches(regex);
System.out.println("qq..."+flag);
}
//检测电话号码格式
//前三位为13x,15x,18x,总共11位,
static void checkTel(){
String tel = "13688888888";
String regex = "1[358]\\d{9}";
boolean flag = tel.matches(regex);
System.out.println("tel..."+flag);
}
}
2.切割
String[] | split(String regex) 根据给定正则表达式的匹配拆分此字符串。 |
String[] | split(String regex, int limit) 根据匹配给定的正则表达式来拆分此字符串。 |
import java.util.regex.*;
public class Demo{
public static void main(String[] args) {
splitDemo("abc 123 iop"," +");
splitDemo("abc.123.iop","\\.");
splitDemo("c:\\desktop\\a.java","\\\\");
splitDemo("acssfwffgyyyyq","(.)\\1+");
//按照叠词完成切割,为了可以让规则的结果被重用,可以将规则封装成一个组,用()完成,组的出现都有编号,从1开始,想要使用已有的组可以用\n(n就是组的编号)的形式来过去==获取
//算几组,看左括号有几个即可,且编号从左往右1开始。比如((())()) 有4组
}
public static void splitDemo(String str,String regex){
String[] arr = str.split(regex);
for(String s:arr){
System.out.println(s);
}
System.out.println("-------");
}
}
3.替换
String | replaceAll(String regex,String replacement) 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。 |
String | replaceFirst(String regex,String replacement) 使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。 |
import java.util.regex.*;
public class Demo{
public static void main(String[] args) {
//将字符串数组替换成#
replaceDemo("wff15168411fwj548486fws15648978f","\\d{5,}","#");
//将叠词替换成&
replaceDemo("fwkkejqqqfizzzzzo","(.)\\1+","&");
//将叠词换成叠词中一个字符
replaceDemo("fwkkejqqqfizzzzzo","(.)\\1+","$1");
}
public static void replaceDemo(String str,String regex,String newStr){
str = str.replaceAll(regex, newStr);
System.out.println(str);
System.out.println("-------");
}
}
4.获取
代码示例:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Demo{
public static void main(String[] args) {
getDemo();
}
public static void getDemo(){
String str = "ming tian jiu yao fang jia le,huo ji.";
String regex = "\\b[a-z]{4}\\b";
System.out.println(str);
//将规则封装成对象
Pattern p = Pattern.compile(regex);
//让正则对象和要作用的字符串相关联。获取匹配器对象
Matcher m = p.matcher(str);
//其实String类中的matches方法就是用Pattern和Matcher对象完成的,只不过被String对象封装后变简单了
//System.out.println(m.matches());
boolean b = m.matches();
System.out.println("..."+b);
//将规则作用到字符串上,并进行符合规则的字串查找
while(m.find()){
System.out.println(m.group()); //用于获取匹配后结果
System.out.println(m.start()+"..."+m.end());
}
}
}
会发现ming没有打印,为什么?
因为m.find()之前,有m.matches()方法,表示已经匹配了一次,所以m.find()是从第二个单词开始查找
5.本地爬虫
获取本地文件中的所有邮箱:import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Demo{
public static void main(String[] args) throws Exception {
getLocalMails();
}
//获取本地文件中邮箱
public static void getLocalMails() throws Exception{
BufferedReader bufr = new BufferedReader(new FileReader("mail.txt"));
String line = null;
String mailRegex = "\\w+@\\w+(\\.\\w)+";
Pattern pattern = Pattern.compile(mailRegex);
while((line = bufr.readLine())!=null){
Matcher matcher = pattern.matcher(line);
while(matcher.find()){
System.out.println(matcher.group());
}
}
}
}
注意文件如果用相对路径时,要把文件放在项目目录下即可,如图是我的文件存放位置:
如果想要实现从网页获取信息,可以参考我另一篇博客(java网页爬虫)http://blog.csdn.net/manfulleo/article/details/51115781