正则表达式
正则表达式:符合一定规则的表达式
作用:用于专门操作字符串的。
特点:用一些特定的符号来表示一些代码操作,这样就简化了书写。
所以学习正则表达式就是在学习一些特殊符号的使用。
好处:可以简化对字符串的复杂操作
弊端:符合定义越多,正则越长,阅读性越差。
具体操作功能:
1、匹配:
String matches(String regex)方法,用规则匹配整个字符串,只要又一次不符合规则,就匹配结束,返回false
代码实例:
/** * 该方法采用正则表达式的方式对QQ号码进行校验 */ public static boolean checkQQRegex(String qq){ String regex = "[1-9]\d{4,14}"; boolean flag = qq.matches(regex); if(flag){ System.out.println(qq); } else { System.out.println("QQ号码输入错误"); } return !flag; }
2、切割:
String split(String regex);
注意切割标识:.和\
.表示任意字符,要使用.作为切割标准,表现转义\.
用\切割时,表示为\\
String str = "zhangsan.lishi.wangwu"; String regex = "\."; String[] arr = str.split(regex); for(String s : arr){ System.out.println(s); } String str = "c:\abc\test.java"; String regex = "\\"; String[] arr = str.split(regex); for(String s : arr){ System.out.println(s); }
组的概念:
当需要重复使用同一个规则时,可以将其封装成组,组会自动编号,调用组只需要用加组号
按照叠词完成切割,为了可以让规则的结果可以被重用,可以将规则封装成一个组,用小括号完成(),组的出现都有编号,从1开始,想要使用已有的组,可以使用 的形式来获取,n为组的编号
((())())一共有四个组,看组必须看左括号,有几个左括号就有几个组,并且,组号也是按照左括号排的。
String str = "ajddflkasssdsjgljqqqqasg"; String regex = "(.)\1+"; String[] arr = str.split(regex); for(String s : arr){ System.out.println(s); }
3、替换:
String replaceAll(String regex,String replacement);特例:特殊符合$,可以用$获取其他正则表达式中的组
public static void main(String[] args) { String str = "iogjsd234235ddajnf1234glkas432jlss54323456skjo"; String regex = "\d"; String newstr = "#"; replaceAll(str,regex,newstr); } /** * 该方法的用于使用正则表达式对字符串进行替换处理 */ public static void replaceAll(String str,String regex,String newstr){ str = str.replaceAll(regex,newstr); System.out.println(str); }
4、获取:将字符串中符合规则的子串取出。
操作步骤:
a) 将正则表达式封装成对象
b) 让正则对象和要操作的字符串相关联
c) 关联后,获取正则匹配引擎
d) 通过引擎对符合规则的子串进行操作,比如取出
Pattern类
正则表达式的编译表示形式。
该类没有构造函数,对外提供了一个静态方法compile(String regex);将给定的正则表达式编译到模式中,即会返回一个Pattern对象
用compile方法可以将正则表达式封装成对象
该类中方法matcher(CharSequence input);可以将Pattern对象和所要操作的字符串相关联。
该方法会返回一个新的匹配器Matcher对象
类Matcher
通过解释Pattern对charactersequence执行匹配操作的引擎
其实String类中的matches方法,用的就是Pattern和Matcher对象来完成的,只不过被String的方法的封装后,用起来较为简单,但是功能却单一。
该类中方法group()能够获得匹配操作所匹配的输入子序列。
如果没有尝试任何匹配,或者以前的匹配操作失败,会抛出IllegalStateException异常。
即要先匹配后才进行获取。
类中方法find(),可以尝试查找与该模式匹配的输入序列的下一个子序列。
此方法从匹配器区域的开头开始,如果该方法的前一次调用成功了并且从那时开始匹配器没有被重置,则从以前匹配操作没有匹配的第一个字符开始。
如果匹配成功,则可以通过start、end和group方法获取更多信息。
当且仅当输入序列的子序列匹配此匹配器的模式时才返回true。
正则的取出,类似以迭代器的方式,必须先判断,然后再取出,判断用find,取出用group
该类中还可以获取匹配的字符串的位置,通过start和end来获得
Start获取该匹配的子串的初始位置,end获得该匹配子串的结束位置
代码示例:
public static void main(String[] args) { String str = "jin tian wo hen gao xing.yin wei wo gan jue zi ji you zhao dao le fen dou de ji qing."; String regex = "\b[a-z]{4}\b"; getString(str,regex); } /** * 该方法用于通过正则表达式的方式获取匹配的字符串 */ public static void getString(String str,String regex){ //1、将正则表达式封装成对象 Pattern pat = Pattern.compile(regex); //2、将正则表达式对象与所要操作的字符串想关联,获得匹配器 Matcher mat = pat.matcher(str); //3、通过匹配器进行匹配,并获得匹配的字符串,打印在控制台 while(mat.find()){ System.out.println(mat.group()); System.out.println(mat.start()+"....."+mat.end()); } }
在用正则表达式解决字符串问题时,到底用四种功能中的哪一个呢,或者哪几个呢?
思考方式:
1、如果只想知道该字符是否对错,使用匹配
2、想要将已有的字符串变成另一个字符串,可以替换
3、想要按照指定的方式将字符串变成多个字符串,可以使用切割,切割其实就是获取规则以为的子串。
4、想要拿到符合需求的字符串子串,可以获取。其实是获取符合规则的子串。
练习:
1、 采用正则表达式的方式,将字符串
* "我我...我我...我要..要要..要要..学学学...学学...编编编...编程.程..程程...程...程"
* 转成"我要学编程"
public static void main(String[] args) { String str = "我我...我我...我要..要要..要要..学学学...学学...编编编...编程.程..程程...程...程"; System.out.println(regexTest_1(regexTest_1(str, "\.+",""), "(.)\1+","$1")); } /** * 该方法用于将字符串按照给定的规则进行处理 */ public static String regexTest_1(String str,String regex,String newstr){ return str.replaceAll(regex, newstr); }
* 练习2:
* 需求:将下列ip地址进行地址段顺序的排序
* 192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30
public static void main(String[] args) { String str = "192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30 2.2.3.2 2.2.2.4"; // sort_1(str); sort_2(str); } /** * 该方法采用字符串自身具备的比较性进行ip地址段顺序排序 */ public static void sort_2(String str){ //1、将ip地址段前面都补零,保证最小字段都能补足为3位 str = str.replaceAll("(\d+)", "00$1"); //2、将ip地址段中超过3位的多余的0清除,保证每个地址段都为3位 str = str.replaceAll("0*(\d{3})", "$1"); Set<String> set = new TreeSet<String>(); //3、按" "切割出每个ip地址,并存入Set中,按照字符串自身比较性排序 for(String s : str.split(" ")){ set.add(s); } for(String s : set){ //4、将排好序的ip地址中多余的0去除后打印 System.out.println(s.replaceAll("0*(\d)", "$1")); } } /** * 该方法用于将传入的ip地址字符串进行按地址段顺序排序 * 思路: * 1、先将传入的字符串按" "切割,将得到的字符串数组中的元素存入set集合中 * 2、对set集合创建比较器,按地址段进行排序 * 3、打印排好序的ip地址 */ public static void sort_1(String str){ //1、将传入的ip地址字符串切割出独立的ip地址 String[] ips = str.split(" +"); //2、定义Set集合,存储ip地址,并定义比较器进行比较排序 Set<String> set = new TreeSet<String>(new Comparator<String>(){ public int compare(String s1,String s2){ String[] ss1 = s1.split("\."); String[] ss2 = s2.split("\."); int temp = 0; for(int x=0;x<4;x++){ temp = Integer.parseInt(ss1[x])-Integer.parseInt(ss2[x]); if(temp!=0) break; } return temp; } }); for(String ip : ips){ set.add(ip); } for(String ip : set){ System.out.println(ip); } }
网页爬虫练习,其实质就是获取网页上的数据,在根据正则表达式方法获取符合要求的字符串
在通过正则获取时,必须注意正则获取的步骤:
1、将正则表达式封装成对象
2、通过Pattern对象关联要处理的数据,并获取匹配器引擎
3、通过Matcher对象,通过对象中方法find判断是否还存在符合要求的数据,通过group方法获取符合要求的数据
4、注意:必须先判断是否存在符合要求的数据后才可以进行获取,若不然或抛出异常。