java基础之正则表达式
2015-12-14 23:38
567 查看
正则表达式是用来操作字符串的规则,我们可以把正则表达式看做一个模板,把字符串放到这个模板中就可以得到我们想要的样子。
(1)字符类
[abc]表示此位置是否含有此字符
[^abc]表示此位置除了abc都可以接收
[a-zA-Z]接收全部字母,不区分大小写
[a-b[m-p]]表示可以接收a到b和M到p的字符集
[a-z&&[^bc]]表示接收a到z但是不包含bc
[a-z&&[^m-p]]表示接收a到z但是不包含m到p的子集
(2)预定义字符类
. 任何字符
\ d 数字0-9
\D 非数字
\s 空白字符[ \t\n\x0B\f\r]
\S 非空白字符
\w 单词字符[a-zA-Z_0-9] ,邮箱使用
\W 非单词字符
注意点:\ 单独出现时是转义字符,而\d是一个整体,所以要写\\d,在正则中只要出现“\”在使用的时候就得写“\\”
(3)Greedy 数量词
X? 表示X出现一次或一次也没有
X* 表示X出现零次或多次
X+ 表示X出现一次或多次
X{n} 表示X出现恰好 n 次
X{n,} 表示X出现至少 n 次
X{n,m} 表示X出现至少 n 次,但是不超过 m 次
(4) 组
组是正则当中一个非常强大的概念,我们可以把一个表达式封装成组,就是把它放在括号当中,组是有编号的,第一个括号包装的为第一组,在这个组之后还可以继续使用这个组的结果。
捕获组可以通过从左到右计算括号来编号。例如,在表达式 ((A)(B(C)))中,存在四个这样的组: 第一组:((A)(B(C))),第二组:(A),第三组: (B(C)),第四组: (C),利用“\\+组的编号”来表示是第几组,例如“\\1”就代表着第一组。而获取组中的内容可以使用”&”,他可以把组中的内容拿到。
(1)匹配:matches(String regex)
返回boolean型,用规则匹配整个字符串,如果有一个不匹配就返回假。
我们通过对一个手机号码进行校验,使用正则的匹配功能,定义一个正则表达式,把手机号码的特点用正则进行描述,然后将手机号码的字符串表现形式按此正则表达式进行匹配。
(2)切割:split(String regex)
返回字符串数组,用指定的正则表达式来切割字符串。
注意点:在切割中我们常用正则来切割URL路径,当我们以“\”作为切割的标准时,在定义正则表达式时要写为“\\”,因为在正则中”\”代表转义字符,所以要多加一个“\”,而URL路径中的“\\”在正则中的表现形式是“\\\\”。
(3)替换:replaceAll(String regex,String str)
返回字符串,以指定的字符串str替换掉字符串中正则表达式regex所匹配到的内容。
(4)获取
通过正则表达式把符合要求的子串从字符串中取出具体操作步骤为:
1>将正则表达式封装成对象,把正则表达式封装成对象的类叫做Pattern,这个类是一个工具类,在这个类中有一个方法compile(String regex),他可以将指定的正则表达式封装成Pattern对象。
2>让正则对象和要操作的字符串相关联,通过Pattern类中的matcher(CharSequence input)方法,将字符串作为参数传入matcher方法中。
3>关联后获取正则匹配引擎,当调用matcher方法时会返回一个Matcher对象,这个Matcher就是一个匹配引擎,他具有更多的方法来操作与之匹配的字符串。
4>启动引擎对符合规则的子串进行操作,我们可以通过Matcher的方法find()方法来将规则作用到字符串上,并进行符合规则的子串查找,然后调用group()方法来返回符合规则的子串,这样就完成了利用正则来获取指定子串。
一. 正则表达式的简介
1.正则表达式的概念
正则表达式是一种规则,那么他用特定的符号来表示代码操作,这样就简化了书写,所以学习正则表达式就是学习一些特殊符号的使用,我们先来了解一下正则表达式的常用符号。(1)字符类
[abc]表示此位置是否含有此字符
[^abc]表示此位置除了abc都可以接收
[a-zA-Z]接收全部字母,不区分大小写
[a-b[m-p]]表示可以接收a到b和M到p的字符集
[a-z&&[^bc]]表示接收a到z但是不包含bc
[a-z&&[^m-p]]表示接收a到z但是不包含m到p的子集
(2)预定义字符类
. 任何字符
\ d 数字0-9
\D 非数字
\s 空白字符[ \t\n\x0B\f\r]
\S 非空白字符
\w 单词字符[a-zA-Z_0-9] ,邮箱使用
\W 非单词字符
注意点:\ 单独出现时是转义字符,而\d是一个整体,所以要写\\d,在正则中只要出现“\”在使用的时候就得写“\\”
(3)Greedy 数量词
X? 表示X出现一次或一次也没有
X* 表示X出现零次或多次
X+ 表示X出现一次或多次
X{n} 表示X出现恰好 n 次
X{n,} 表示X出现至少 n 次
X{n,m} 表示X出现至少 n 次,但是不超过 m 次
(4) 组
组是正则当中一个非常强大的概念,我们可以把一个表达式封装成组,就是把它放在括号当中,组是有编号的,第一个括号包装的为第一组,在这个组之后还可以继续使用这个组的结果。
捕获组可以通过从左到右计算括号来编号。例如,在表达式 ((A)(B(C)))中,存在四个这样的组: 第一组:((A)(B(C))),第二组:(A),第三组: (B(C)),第四组: (C),利用“\\+组的编号”来表示是第几组,例如“\\1”就代表着第一组。而获取组中的内容可以使用”&”,他可以把组中的内容拿到。
2.正则表达式的使用
正则表达式可以应用于操作字符串的两个方法中,作为模板来格式化这个字符串,这两个方法分别是:(1)匹配:matches(String regex)
返回boolean型,用规则匹配整个字符串,如果有一个不匹配就返回假。
我们通过对一个手机号码进行校验,使用正则的匹配功能,定义一个正则表达式,把手机号码的特点用正则进行描述,然后将手机号码的字符串表现形式按此正则表达式进行匹配。
/* * 校验手机号 * 1.利用键盘录入信息 * 2.定义正则表达式,描述手机号 * 3.利用matches方法判断手机号是否正确 * */ public class Test1 { public static void main(String[] args) { //利用Scanner接收键盘录入手机号 Scanner sc = new Scanner(System.in); while(true) { //获取录入数据 String str = sc.next(); //如果输入“out”程序结束不再录入 if("out".equals(str)) break; /*定义正则表达式描述手机号信息 * [1]指第一位必须是数字1 * [358]指第二位数字必须是3或5或8 * \\d第二位后必须是数字 * {9}代表第二位后必须有9位数 * */ String regex = "[1][358]\\d{9}"; //判断是录入数据是否是手机号,利用String的matches方法 if(str.matches(regex)) { System.out.println("您输入手机号正确!"); break; }else { System.out.println("输入错误,请重新输入!"); } } } }
(2)切割:split(String regex)
返回字符串数组,用指定的正则表达式来切割字符串。
注意点:在切割中我们常用正则来切割URL路径,当我们以“\”作为切割的标准时,在定义正则表达式时要写为“\\”,因为在正则中”\”代表转义字符,所以要多加一个“\”,而URL路径中的“\\”在正则中的表现形式是“\\\\”。
public class SplitDemo2 { public static void main(String[] args) { split_1(); System.out.println(); split_2(); } /* * 正则切割示例1 * 将字符串“小宏 小蓝 小绿 小黑”按空格切割,得到文字。 * */ private static void split_1() { //定义字符串 String str = "小宏 小蓝 小绿 小黑"; //定义正则,因为要按空格切,空格数目不确定使用+来表示 String regex = " +"; split(str,regex); /* * 结果是: * 小宏 小蓝 小绿 小黑 * */ } /* * 正则切割示例2 * 将一堆字符串按照叠词切割,例如将 * “heimazzxiaohongzzxiaoheizzxiaohua” * 按照“zz”进行切割。利用组的概念。 * */ private static void split_2() { String str = "heimazzxiaohongzzxiaoheizzxiaohua"; //定义正则,(.)组代表任意字符,\\1代表着后一位和组是一样的内容 String regex = "(.)\\1"; split(str,regex); /* * 结果是: * heima xiaohong xiaohei xiaohua * */ } //切割打印功能函数 private static void split(String str, String regex) { String[] strs = str.split(regex); for(String s : strs) { System.out.println(s); } } }
(3)替换:replaceAll(String regex,String str)
返回字符串,以指定的字符串str替换掉字符串中正则表达式regex所匹配到的内容。
class Test3 { public static void main(String[] args) { //将字符串中的数字替换成数组 String str1 = "xiaohong12adsf3321adfads"; replaceAll(str1,"\\d","#"); //将叠词替换成# String str2 = "dfasdkkyasdaalslkddddqqffea"; replaceAll(str2,"(.)\\1+","#"); //将重叠字母替换成单个字母: "$1" String str3 = "xiaohong hhhhh xiaolv yyyy xiaolan"; replaceAll(str3,"(.)\\1+","$1"); } //替换功能函数 public static void replaceAll(String str,String reg,String newStr) { str = str.replaceAll(reg,newStr); System.out.println(str); } /* * 结果是: * xiaohong##adsf####adfads dfasd#yasd#lslk###ea xiaohong h xiaolv y xiaolan * * */ }
(4)获取
通过正则表达式把符合要求的子串从字符串中取出具体操作步骤为:
1>将正则表达式封装成对象,把正则表达式封装成对象的类叫做Pattern,这个类是一个工具类,在这个类中有一个方法compile(String regex),他可以将指定的正则表达式封装成Pattern对象。
2>让正则对象和要操作的字符串相关联,通过Pattern类中的matcher(CharSequence input)方法,将字符串作为参数传入matcher方法中。
3>关联后获取正则匹配引擎,当调用matcher方法时会返回一个Matcher对象,这个Matcher就是一个匹配引擎,他具有更多的方法来操作与之匹配的字符串。
4>启动引擎对符合规则的子串进行操作,我们可以通过Matcher的方法find()方法来将规则作用到字符串上,并进行符合规则的子串查找,然后调用group()方法来返回符合规则的子串,这样就完成了利用正则来获取指定子串。
/* * 利用指定的规则来获取字符串中的子串 * 获取“heima nihao wo shi xiao hong wo lai le” * 中由四位字符组成的词组 * */ public class Test4 { public static void main(String[] args) { String str = "heima nihao,wo shi xiao hong,wo lai le!"; //定义正则,定义四字单词需要用到边界字符“\b” String regex = "\\b[a-z]{4}\\b"; //把正则封装成对象 Pattern pt = Pattern.compile(regex); //获取匹配引擎 Matcher mc = pt.matcher(str); //将正则作用于字符串上,并进行符合规则的查找 while(mc.find()) { //取出符合规则的子串 String ss = mc.group(); System.out.println(ss); } } } /* * 打印: * xiao hong * */
3.正则的弊端
当我们需要的规则越多,定义的正则表达式就越长,这样阅读性越差,一个复杂的正则表达式让人不能一眼就看出他的作用。而且使用正则之后当输入错误无法精准的定位错误出现的原因。二. 正则表达式的练习
1. 去掉标点和叠词
/* * 将以下字符串去重复和省略号 * “我我...我我...要....学学学...编....编...程“ * */ public class Test5 { public static void main(String[] args) { String str = "我我...我我...要....学学学...编....编...程"; /*分析正则表达式如何定义 * 1.需要去省略号 * 2.去叠词 * */ //去省略号,使用替换 String newStr1 = str.replaceAll("[.]+",""); System.out.println(newStr1); //去叠词,使用组 String newStr2 = newStr1.replaceAll("(.)\\1+", "$1"); System.out.println(newStr2); } } /* * 打印: * 我我我我要学学学编编程 我要学编程 */
2.对IP地址进行排序
/* * 使用正则对一堆ip地址进行排序 * 192.168.0.1 102.23.45.23 10.10.20.10 2.3.3.3 9.132.43.21 * * 让ip地址按照字符串自然顺序,2排到10的后面,所以要让他们每一段都是3位, * 即010对应002时,002就排到010的前面。 * 思路: 1.利用正则将每一段的ip地址前补两个0 2.将每一段只保留3位 3.将3位的ip地址进行排序 4.将ip地址进行还原 * */ public class Test6 { public static void main(String[] args) { String ip = "192.168.0.1 102.23.45.23 10.10.20.10 2.3.3.3 9.132.43.21"; //补两个0 String newIp1 = ip.replaceAll("(\\d+)", "00$1"); //保留三位 String newIp2 = newIp1.replaceAll("0*(\\d{3})", "$1"); //将三位数的ip地址进行排序 String[] strs = newIp2.split(" +"); Arrays.sort(strs); //遍历排完序的数组,并将他们还原 for(String s:strs) { System.out.println(s.replaceAll("0*(\\d+)", "$1")); } } } /* * 打印: * 2.3.3.3 9.132.43.21 10.10.20.10 102.23.45.23 192.168.0.1 * * */
3.网页爬虫,获取网页中邮箱
我们可以利用正则来匹配网页上的数据,来获取邮箱名,邮箱的正则表达式较为精准的是“\\w+@\\w+(\\.[a-zA-Z]+){1,3}”,这种格式获取到的邮箱绝大多数为正常的。我们来看一下如何在网页上获取邮箱:/* * 建立一个网页爬虫,获取网页中的邮箱 * 1.自定义一个URL访问网页 * 2.获取网页中的内容 * 3.定义正则匹配网页中信息,获取到邮箱 * 4.将获取到的邮箱打印出来并写入本地文件中 * */ public class Test7 { public static void main(String[] args) { PrintWriter pw = null; BufferedReader br = null; try { //定义输入流,将获取到的邮箱写入到本地文件 pw = new PrintWriter(new FileWriter("e://email.txt"),true); //自定义客户端访问网页 URL u = new URL("http://www.itheima.com/newhelp/393.html"); URLConnection uc = u.openConnection(); br = new BufferedReader( new InputStreamReader(uc.getInputStream())); String line = null; //定义正则用来匹配邮箱 String regex = "\\w+@\\w+(\\.[a-zA-Z]+){1,3}"; //把正则封装成对象 Pattern p = Pattern.compile(regex); while((line = br.readLine())!=null) { //拿到引擎匹配当前行 Matcher mc = p.matcher(line); while(mc.find()) { String str = mc.group(); System.out.println(str); pw.println(str); } } } catch (Exception e) { e.printStackTrace(); }finally { pw.close(); try { if(br==null) br.close(); } catch (IOException e) { e.printStackTrace(); } } } } /* * 打印: * heima@csdn.net * */
相关文章推荐
- Java开发者必备的六款工具
- JPA--Caused by: javax.persistence.PersistenceException: [PersistenceUnit: mysqlJPA] Unable to configure EntityManagerFactory
- java字符串
- 06 java中常量以及常量池
- java相关-- 工作笔记第一天
- springMVC与struts2的区别
- springMVC是什么
- spring是什么
- 【JavaWeb笔记】Servlet的生命周期
- Struts2-由于没有添加默认的拦截器导致拦截器出现为空的异常
- 【JavaWeb笔记】部署Srevlet
- Struts2 Interceptor的例子
- 第三个spring冲刺第8天
- 【JavaWeb笔记】Servlet和JSP的区别
- myeclipse Available Memory is low 问题解决方法
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(四)之Operators
- 朝花夕拾——Java的synthetic修饰词
- 给jdk写注释系列之jdk1.6容器(2)-LinkedList源码解析
- Java学习笔记(4):2.数组
- 【待解决】使用JUnit时报错java.lang