正则表达式__【匹配、切割、替换】【获取:Pattern & Matcher】【网页爬虫(蜘蛛)】

前端之家收集整理的这篇文章主要介绍了正则表达式__【匹配、切割、替换】【获取:Pattern & Matcher】【网页爬虫(蜘蛛)】前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。


概念:

正则表达式:即符合一定规则的表达式
作用:专门用于操作字符串
特点:用一些特定的符号来替代一些代码操作,简化书写
学习正则表达式就是在学习指定其规则的符号的使用,即如何定义规则,详细方法参见API文档Pattern中正则表达式的规则组成
优点:简化字符串操作步骤
弊端:符号定义多时,正则越长,阅读性越差

具体操作功能

1,匹配:String matches()方法;设定regex规则,只要有一处不匹配,就返回false
2,切割:String split()方法就是 将regex作为参数传入,可以定义regex实现复杂的切割
3,替换:String replaceAll()方法
  1. class RegexDemo
  2. {
  3. public static void main(String[] args)
  4. {
  5. // checkQQ_1();String类传统方法
  6. //一、匹配 qq号验证
  7. // checkQQ_2("667788","[1-9][0-9]{4,9}");定义规则:[0-9]首位1~9;[0-9]{4,9}其它位为数字,出现次数范围
  8. //手机号验证
  9. // checkTel("18688888888","1[358]\\d{9}");定义规则首位1,第二位为3/5/8,后面9位数字,正则表达式的构造字符\d要加转义字符\
  10. //二、切割
  11. // splitDemo("zhangsan lisi wangwu"," +");//一个或多空格切割
  12. //"."切割
  13. // splitDemo("zhangsan.lisi.wangwu","\\.");//"."表示任意字符;"\."表示正则表达式中的".",前面要加转义字符>>"\\."
  14. //双"\\"切割
  15. // splitDemo("d:\\java\\demo.java","\\\\");//四个"\\\\"来表示两个\\;因为要加转义\
  16. // 按照叠词切割;"组"的概念
  17. // splitDemo("hssbkkdaa","(.)\\1+");//规则:叠词重复一次或多次
  18. //三、替换
  19. String str = "tel:18688886666QQ22876686MM548434";//将字符串中数字替换成#
  20. replaceAllDemo(str,"\\d{5,}","#");//规则:数字,出现5次以上
  21. String str2 = "hdsdsdddggvmmmop";//将叠词替换成单个字母(ddd>>d)
  22. replaceAllDemo(str2,"(.)\\1+","$1");
  23. }
  24. public static void replaceAllDemo(String str,String reg,String newStr ){
  25. str = str.replaceAll(reg,newStr); //String类方法,正则表达式的复杂替换
  26. System.out.println(str);
  27. }
  28. public static void splitDemo(String str,String reg){
  29. String[] arr = str.split(reg);//根据规则来切割
  30. System.out.println(arr.length);
  31. for (String s : arr )
  32. {
  33. System.out.println(s);
  34. }
  35. }
  36. //匹配手机号:只是能以13 15 18 开头的11位数字
  37. public static void checkTel(String tel,String telReg){ //匹配
  38. System.out.println(tel.matches(telReg));
  39. }
  40. public static void checkQQ_2(String qq,String regex) //二、String类的matches方法
  41. {
  42. boolean flag = qq.matches(regex); //判断输入的qq与规则是否匹配,返回值为boolean型
  43. if (flag)
  44. System.out.println("QQ: "+qq);
  45. else
  46. System.out.println("QQ号有误,请重新输入!");
  47. }
  48.  
  49. public static void checkQQ_1()//一、使用String类中方法组合完成需求,比较复杂
  50. {
  51. String qq = "286345";
  52. int len = qq.length();
  53. if (len>=5 && len<=10) //1,号码长度
  54. {
  55. if (!(qq.startsWith("0")))//2,String类方法,判断字符串是否以0开头
  56. {
  57. try
  58. {
  59. long l = Long.parseLong(qq);//将数字字符串转成数字
  60. System.out.println("QQ: "+qq);
  61. }
  62. catch (NumberFormatException e)//会如果不是纯数字字符串,会抛出数字转换异常
  63. {
  64. System.out.println("QQ号为0~9的数字");
  65. }
  66.  
  67. /* char[] arr = qq.tocharArray();//将字符串转成字节数组
  68. boolean flag = true;//设置标记
  69. for (int x=0; x<arr.length; x++ ){
  70. if (! (arr[x]>='0' && arr[x]<='9')){//3,判断字符数组是否为数字字符
  71. flag = false;
  72. break;
  73. }
  74. }
  75. if (flag){
  76. System.out.println("QQ: "+qq);
  77. }
  78. else{
  79. } */
  80. System.out.println("QQ号为0~9的数字");//3,}
  81. else{
  82. System.out.println("不能以0开头");//2,}
  83. }
  84. else{
  85. System.out.println("号码长度为5~10位"); //1,}
  86. }
  87. }

使用String类中方法组合完成需求,比较复杂,使用正则表达式,用“符号”替换代码,可以大大简化书写

组的概念:
按照叠词完成切割,为了可以让叠词的结果可以被重用,可以将规则用()封装成一个组,组的出现都有编号\n(编号n)
想要使用已有的组可以通过\n的形式来获取;有几个()就有几个组


正则表达式第四个功能获取

将字符串中符合规则的子串取出;切割得到的是规则以外的,获取得到的是符合规则的
操作步骤:
1,将正则表达式封装成对象
2,将正则对象和要操作的字符串相关联
3,获取正则匹配引擎
4,通过引擎对符合规则的子串进行操作,如取出

获取涉及到两个类对象:

Pattern类和Matcher类
Pattern类没有构造方法
通过其compile()方法将正则封装成对象
通过其matcher()方法获取匹配引擎,返回此模式的新匹配器
matcher();将正则对象和要操作的字符串相关联,获取匹配器对象
charSequence接口,字符序列
要分清楚matcher()方法与matches()方法的区别,前者返回对象,后者返回boolean
Matcher类,匹配器
方法
find();find方法将规则作用到字符串上,进行符合规则的子串查找
group();group方法获取匹配结果

  1. import java.util.regex.*;
  2. class RegexDemo2
  3. {
  4. public static void main(String[] args)
  5. {
  6. getDemo();
  7. }
  8. public static void getDemo()
  9. {
  10. String str = "jin tian hui jia le,haha. ";
  11. String reg = "\\b[a-z]{3}\\b"; //\\b表示字符边界
  12. Pattern p = Pattern.compile(reg);//将正则封装成对象
  13. Matcher m = p.matcher(str); //将正则对象和要操作的字符串相关联,获取匹配器对象
  14. // System.out.println("Matcher: "+m.matches());//
  15. while (m.find())//find方法将规则作用到字符串上,进行符合规则的子串查找
  16. {
  17. System.out.println(m.group());//group方法获取匹配结果
  18. }
  19. }
  20. }

运行结果:


注意事项:同一个匹配器使用的是同一个索引位,如果之前对字符串进行操作,匹配器在继续操作时会继续从原来终止索引位开始操作
如:在获取之前先对该字符串进行判断,获取位置就会从该判断结束的位置开始

运行结果如图:


分析:规则为三个字符,方法natcher判断"jin"之后返回false,此时索引停留在“tian"上,下面的fand()方法就从"tian"开始查找;所以就获取不到“jin”


正则表达式的操作思路

1,如果只想知道该字符是否符合标准,使用匹配
2,就要将已有的字符串改成另一个字符串,替换
3,想要按照指定的方式将字符串转成多个子串。切割
4,想要拿到符合需求的字符串子串,获取

练习:

  1. import java.util.*;
  2. class RegexTest
  3. {
  4. public static void main(String[] args)
  5. {
  6. // test_1();
  7. // ipSort();
  8. checkMail();
  9. }
  10. //一、需求:将字符串转成:我要进黑马!
  11. public static void test_1()
  12. {
  13. String str = "我我...我我我...我...要要...要要...进进...进进进..进..黑...黑黑...马..!";;
  14. str = str.replaceAll("\\.+",""); //1,先将"."去掉
  15. System.out.println(str);
  16. str = str.replaceAll("(.)\\1+","$1");//2,然后将多个重复的内容转成单个内容
  17. System.out.println(str);
  18. }
  19. /*
  20. 二、需求:将ip地址进行地址段顺序的排序
  21. 192.168.1.100 110.56.89.13 2.2.2.2 10.10.10.10
  22. 要处理的问题:地址段数字直接比较时由于位数不同会导致“110<2”的情况
  23. 解决思路:还按照字符串自然顺序,将不足三位的数字补足三位
  24. 1,按照每一段需要的0补齐,保证每一段至少有位
  25. 2,将每一段只保留三位,将多余的0去除
  26. */
  27. public static void ipSort()
  28. {
  29. String ip = "192.168.1.100 110.56.89.13 2.2.2.2 10.10.10.10";
  30. //补两个0,每一段至少三位
  31. ip = ip.replaceAll("(\\d+)","00$1");//规则:连续的数字(),规则被重用,都在前面加两个0
  32. System.out.println(ip);
  33. //将多余的0去除,只留下三位
  34. ip = ip.replaceAll("0*(\\d{3})","$1");//规则:0出现0次或多次(后面跟三个数字)$1取结尾
  35. System.out.println(ip); //$N 表示匹配后,被正则中第N个括号所获取内容
  36. String[] arr = ip.split(" +");//切割
  37. TreeSet<String> ts = new TreeSet<String>();
  38. for (String s : arr ){ //将地址中ip存入TreeSet集合,自动排序
  39. ts.add(s);
  40. }
  41. for (String s : ts ){ //遍历获取;定义规则,去除前面的0
  42. System.out.println(s.replaceAll("0*(\\d+)","$1"));
  43. }
  44. }
  45. /*
  46. 三、需求:对邮件地址进行校验
  47. 规则:邮箱名:[字母数字下划线]{6~12位} @ [字母数字如qq/163等] . [后缀名,子母com/cn等]
  48. */
  49. public static void checkMail()
  50. {
  51. String mail = "hahaha@163.com.cn";
  52. String reg = "[a-zA-z0-9_]{6,12}@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";//较为精确的匹配
  53. reg = "\\w+@\\w+(\\.\\w+)+";//相对不太精确的匹配<span style="font-family: Arial,Helvetica,sans-serif;">(1@1.1)</span>
  54. // mail.indexOf("@") !=-1; //简陋的匹配(@)
  55. System.out.println(mail.matches(reg));
  56. }
  57. }

运行结果:

1,去重复


2,ip管理:



获取练习:网页爬虫(蜘蛛)

获取指定页面中符合规则的信息,如邮箱

定义正则,扫描网页,获取页面中的所有邮箱地址

实现:

  1. import java.io.*; //io包
  2. import java.util.regex.*;//正则包
  3. import java.net.*; //URL
  4. class RegexTest2
  5. {
  6. public static void main(String[] args) throws Exception
  7. {
  8. // getMails_1();
  9. getMails_2();
  10. }
  11. //二、获取互联网上网页中的邮箱
  12. public static void getMails_2() throws Exception
  13. {
  14. URL url = new URL("http://tieba.baidu.com/p/2314539885");
  15. URLConnection con = url.openConnection();
  16. BufferedReader bufIn = new BufferedReader(new InputStreamReader(con.getInputStream()));
  17. myRegex(bufIn);
  18. }
  19. //一、获取指定文档中邮件地址
  20. //使用获取功能,用到Pattern 和Matcher类
  21. public static void getMails_1() throws Exception
  22. {
  23. BufferedReader bufr = new BufferedReader(new FileReader("1.txt"));//读取文档
  24. myRegex(bufr);
  25. }
  26. public static void myRegex(BufferedReader buf) throws Exception
  27. {
  28. String regex = "\\w+@\\w+(\\.\\w+)+";//邮箱规则
  29. Pattern p = Pattern.compile(regex); //1,将规则封装成对象
  30. String line = null;
  31. while ((line=buf.readLine()) !=null)
  32. {
  33. Matcher m = p.matcher(line); //2,获取匹配器
  34. while (m.find()) //匹配器方法,查找符合规则子串
  35. {
  36. System.out.println(m.group());//获取字串
  37. }
  38. }
  39. }
  40. }
这个执行获取操作的网页爬虫真正体现了正则表达式的威力,随便试了一个贴吧里资源帝留邮箱的帖子页面,轻易就抓取了几十个邮箱地址

运行结果:


小结:

正则表达式的强大之处在于在定义regex正则时,寥寥几个符号就能取代大量的String 字符串操作,大大的简化了书写,提高开发效率;缺点是规则较多时阅读性较差,站在开发的角度来讲,其好处是远远大于弊端的。

获取操作要重点掌握,Pattern类和Matcher类

猜你在找的正则表达式相关文章