JAVA学习正则表达式。
正则表达式:主要应用于操作字符串,通过一些特定的符号来体现
举例:
QQ号的校验
6~9位,0不得开头,必须是数字
String类中有matches方法
matches(String regex)
告知此字符串是否匹配给定的正则表达式。
regex,就是给定的正则表达式
- public static void checkQQ() {
- //第一位是数字1-9,第二位以后是0-9,除去第一位数剩下数字位数范围是5到8位
- String regex = ”[1-9][0-9]{5,8}”;//正则表达式
- String qq = ”123459″;
- boolean flag = qq.matches(regex);
- System.out.println(qq+” : ”+flag);
- }
PS:正则表达式虽然简化了书写,但是代码的阅读性极差
符号意义
正则表达式难就难在符号太多。
预定义字符类 | |
---|---|
. | 任何字符(与行结束符可能匹配也可能不匹配) |
\d | 数字:[0-9] |
\D | 非数字: [^0-9] |
\s | 空白字符:[ \t\n\x0B\f\r] |
\S | 非空白字符:[^\s] |
\w | 单词字符:[a-zA-Z_0-9] |
\W | 非单词字符:[^\w] |
字符类 | |
---|---|
[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](减去) |
边界匹配器 | |
---|---|
^ | 行的开头 |
$ | 行的结尾 |
\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,作为捕获组 |
Back 引用 | |
---|---|
\n | 任何匹配的 nth捕获组 |
- public static void check() {
- <span style=”white-space:pre”> </span>
- String string = ”aoooooz”;
- String regex = ”ao{4,}z”;//正则表达式
- boolean flag = string.matches(regex);
- System.out.println(string+” : ”+flag);
- }
常见功能
1.匹配 2.切割 3.替换 4.获取
匹配:用的是String类中的matches方法
- public static void check() {
- //匹配手机号码是否正确
- String tel = ”18753377511″;
- //第一位是1,第二位是3或5或8
- //String regex = ”1[358][0-9]{9}”;
- String regex = ”1[358]\\d{9}”;
- //字符串中\,代表转义,所以再加上一个”\”将”\”转义
- boolean flag = tel.matches(regex);
- System.out.println(tel+” : ”+flag);
- }
切割:就是以前用的String类中的split(String regex)方法,以前用的是” “,空格一般的非特殊符号,都可看作规则
空格
- public static void check() {
- //以空格为分割,切割,空格可能出现多次
- String str = ”a b c d e f”;
- String regex = ” +”;//空格出现1次或者多次
- String[] line = str.split(regex);
- for(String i : line){
- System.out.println(i);
- }
- }
点,PS:点本身在正则表达式中是特殊符合
- String str = ”a.b.c.d.e..f”;
- String regex = ”\\.+”;//\.转义后还是.,所以再加一个\
- String[] line = str.split(regex);
以叠词为分割
正则用()来封装成组
所以叠词就可以表示为,.代表任意字符,(.)封装成组,(.)\\1,代表余下都和第一组相同
- String str = ”a@@@b####c…dtttef”;
- String regex = ”(.)\\1+”;//
- String[] line = str.split(regex);
组:((A)(B(C))),共有几组,哪几组
以左括号数,
((A)(B(C))) 1
(A) 2
(B(C)) 3
(C) 4
无括号就是第0组
替换:
replaceAll(String regex,String replacement)
使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
replaceFirst(String regex,String replacement)
使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
- public static void check() {
- //把叠词变为一个字符
- String str = ”abgggggcffffdggggs”;
- String regex = ”(.)\\1+”;//
- str = str.replaceAll(regex, ”$1″);
- System.out.println(str);
- }
PS:美元符号在其他参数中,可以对前一个参数中的已有的正则规则的获取
- public static void check() {
- //18753377511 -> 187****7511
- String str = ”18753377511″;
- String regex = ”(\\d{3})\\d{4}(\\d{4})”;
- System.out.println(str);
- str = str.replaceAll(regex, ”$1****$2″);
- System.out.println(str);
- }
获取
正则本身就是一个对象
Pattern类
指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建Matcher
对象,依照正则表达式,该对象可以与任意字符序列
匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式。
//将正则的规则进行对象的封装
//Pattern p = Pattern.compile(“a*b”);
//通过正则对象的matcher方法字符串相关联,获取对字符串操作的匹配器对象Matcer
//Matcher m = p.matcher(“aaaab”);
//通过Matcher匹配器对象的方法对字符串进行操作
//boolean b = m.matches();
Matcher类
- public static void check() {
- String str = ”ni hao,wohao,ta ye hao”;
- String regex = ”\\b[a-z]{3}\\b”;//\\b :单词边界
- Pattern p = Pattern.compile(regex);
- Matcher m = p.matcher(str);
- while(m.find())//想要获取,就要先找,有没有,有才能获取
- {
- System.out.println(m.group());
- System.out.println(m.start()+” : ”+m.end());//获取起始下标
- }
- }
练习:
将aaa…aa..aaa…bbb…b…bbb…ccc…ccc 变为 abcd
- public static void test() {
- String str = ”aaa…aa..aaa…bbb…b…bbb…ccc…ccc”;
- System.out.println(str);
- String regex = ”\\.+”;
- str = str.replaceAll(regex, ”");//去点
- regex = ”(.)\\1+”;
- str = str.replaceAll(regex, ”$1″);//去叠词
- System.out.println(str);
- }
排序IP地址
- public static void test() {
- // String str = ”192.0.0.1 127.0.0.24 3.3.3.5 150.15.3.41″;
- // System.out.println(“ip : ”+str);
- // String regex = ” +”;
- // String[] strs = str.split(regex);
- //
- // TreeSet<String> ts = new TreeSet<String>();//自动排序
- // for(String s : strs){
- // ts.add(s);
- // }
- // for(String s : ts){//这样排,是按照字符串排序
- // System.out.println(s);
- // }
- //所以在每个ip的每段数字,就用两个0补全
- String str = ”192.0.0.1 127.0.0.24 3.3.3.5 150.15.3.41″;
- String regex = ”(\\d+)”;
- str = str.replaceAll(regex, ”00$1″);
- System.out.println(“补0 : ”+str);
- regex = ”0*(\\d{3})”;
- str = str.replaceAll(regex, ”$1″);
- System.out.println(“保留3位 : ”+str);
- regex = ” +”;
- String[] strs = str.split(regex);
- TreeSet<String> ts = new TreeSet<String>();//自动排序
- for(String s : strs){
- ts.add(s);
- }
- for(String s : ts){
- System.out.println(s.replaceAll(“0*(\\d+)”, ”$1″));
- }
- }
邮箱地址的简单校验
- public static void test() {
- String mail = ”aa_a@163.com.cn”;
- String regex = ”\\w+@\\w+(\\.[a-zA-Z]{2,3})+”;//+代表一次或多次
- boolean flag = mail.matches(regex);
- System.out.println(mail+” : ”+flag);
- }
注意:开发时,正则阅读性差,会不断验证,然后封装起来
练习:网页爬虫:一个程序用于在互联网中获取符合指定规则的数据
爬取邮箱地址。
- public class asd {
- public static void main(String[] args) throws Exception {
- //List<String> list = getmail();//本地
- List<String> list = getweb();//网络
- for(String i : list){
- System.out.println(i);
- }
- }
- public static List<String> getweb() throws Exception{
- //URL url = new URL(“http://192.168.0.1:8080/myweb/mymail.html”);
- URL url = new URL(“http://news.baidu.com/”);
- BufferedReader brin = new BufferedReader(new InputStreamReader(url.openStream()));
- String mail_regex = ”\\w+@\\w+(\\.\\w+)+”;
- Pattern p = Pattern.compile(mail_regex);
- List<String> list = new ArrayList<String>();
- String line = null;
- while((line = brin.readLine())!=null){
- Matcher m = p.matcher(line);
- while(m.find()){
- list.add(m.group());
- }
- }
- return list;
- }
- public static List<String> getmail() throws Exception {
- //1.读取源文件
- BufferedReader br = new BufferedReader(new FileReader(“g:\\mymail.html”));
- String mail_regex = ”\\w+@\\w+(\\.\\w)+”;
- Pattern p = Pattern.compile(mail_regex);
- List<String> list = new ArrayList<String>();
- String line = null;
- //2.对读取的数据进行规则的匹配,从中获取符合规则的数据
- while((line = br.readLine())!=null){
- Matcher m = p.matcher(line);
- while(m.find()){
- //3.将符合规则的数据存储到集合
- list.add(m.group());
- }
- }
- return list;
- }
- }