正则表达式
概述:
正则表达式:符合一定规则的表达式
作用:
用于专门操作字符串,描述共享该模式的一组字符串。
在java中有String类专门操作字符串为什么还要正则表达式呢?
因为这些功能太简单,组合起来功能代码太多
特点:
用于一些特定符号来表示一些代码操作。这样就简化了书写。
所以学习正则表达式就是在学习一些特殊符号的使用
弊端:
符号定义的愈多,正则表达式越长所以阅读性越差
常见特殊符号:
字符:
X 字符x
\\ 反斜线字符
\t 制表符
\n 换行符
\r 回车符
\f 换页符
\e 转义符
字符类
[abc] a,b或c(简单类)
[^abc] 除了abc的任何字符
[a-d[m-p]] a到d或m到p即取并集
[a-z&&[def]] d,e,f即取交集
[a-z&&[^bc]] 取的是a到z,减去b和c
[a-z&&[^m-p]] 取的是a到z,减去m到p
预定义字符类
. 任何字符
\d 数字:[0-9]
\D 非数字:[^0-9]
\s 空白字符:[\t\n\xOB\f\r]
\S 非空白字符:[^\s]
\w 单词字符[a-zA-Z_0-9]
\W 非单词字符[^\w]
边界匹配器
^ 行的开头
$ 行的结尾
\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次
具体操作功能:
1, 匹配:
在String类中方法boolean String matches()//告知此字符串是否匹配给定的正则表达式
示例:
要求输入5~15位的qq号码,要求0不能开且只能是数字。
- Import java.util.regex;
- class QQDemo{
- public static void main(String[] args) {
- String qq = "1323wr55424";
- //方式三:利用正则表达式来实现
- String regex = “[1-9]\\d{4-14}”;//第一位范围是1到9的数字,第二位或到第十五位的必须是0到9的数字
- //用String类里的matches()判断是否符合规范
- if(qq.macthes(regex)){
- System.out.println(qq);
- }
- else{
- System.out.println(“你输入的字符非法”);
- }
- /*int len = qq.length();
- if (len>=5&&len<=15){
- if (!qq.startsWith("0")){
- //方式二:利用封装基本数据类型出现的非数字报异常特点,但是方法不易想到
- try{
- long l = Long.paseLong(qq);
- }
- catch (NumberFormatException e){
- System.out.println("输入的字符非法);
- }*/
- /*方式一:依次判断,但是速度慢效率低代码臃肿
- char[] ch = qq.toCharArray();
- boolean flag = true;
- for (int x=0;x<=ch.length ;x++ ){
- if (!(ch[x]>'0'&&ch[x]<='9')){
- flag = false;
- break;
- }
- }
- if (flag){
- System.out.println(qq);
- }
- else{
- System.out.println("输入的字符非法");
- }
- }
- else{
- System.out.println("不能以0开头");
- }
- }
- else{
- System.out.println("你输入的长度非法");
- }
- }*/
- }
- 示例二:
- import java.util.regex.*;
- class Demo{
- public static void main(String[] args) {
- //匹配手机号段
- //13xxx 15xxx 18xxx
- String haoma = "13837659876";
- String regex = "1[358]\\d{9}";
- if (haoma.matches(regex)){
- System.out.println(haoma);
- }
- else{
- System.out.println("手机号非法");
- }
- }
- }
2,切割:
String类中的String[] split(String regex) 根据给定正则表达式的匹配拆分此字符串。
示例:
- import java.util.regex.*;
- class Demo{
- public static void main(String[] args) {
- //复杂切割,如“张三 李四 王五 周期”,之间空格不确定数
- //这时可以用"空格+"即多个空格来切
- splitDemo("张三 李四 王五 周期"," +");
- //注意不能用“.”直接切,他是个特殊符号。需用\\.来切
- splitDemo("张三.李四.王五.周期","\\.");
- /*切割叠词切叠词多少不限,这时需要用到组,(.)\\1+;
- 按照叠词切割可以让规则的结果被重用,可以将规则封装成一个组,
- 用()完成。组的出现都有编号,从1开始,想要使用已有的组可以通过
- \n(n就是组的编号)的形式来获取
- */
- splitDemo("errruyuuuussytcd","(.)\\1+");
- }
- public static void splitDemo(String str,String reg){
- String[] names = str.split(reg);
- for(String name:names){
- System.out.println(name);
- }
- }
- }
3,替换:
String类中的String replaceAll(String regex,String replacement)
示例:
- import java.util.regex.*;
- class Demo{
- public static void main(String[] args) {
- String replace1 = "shjgdhhawujjjjlaiw";//将重复的字符替换成#。
- String replace3 = "shjg234132535dhhawuj11242353532jjjla34iw";//将连续5个以上的数字替换成#。
- String replace2 = "shjgdhhawujjjjlaiw";//将重复的字符替换成单个,通过$来获取组的元素
- replaceAll(replace1,"(.)\\1+","#");
- replaceAll(replace3,"\\d{5,}","#");
- replaceAll(replace2,"(.)\\1+","$1");
- public static void replaceAll(String str,String reg,String newstr){
- String str1 = str.replaceAll(reg,newstr);
- System.out.println(str1);
- }
- }
获取:
将字符串中的符合规则的子串取出。
操作步骤:
1, 将正则表达式封装成对象
2, 让正则对象和要操作的字符串相关连
3, 关联后,获取正则匹配引擎。
4, 通过引擎对符合规则的子串进行操作,比如取出。
查询API在java.Util.regex中有Pattern类
正则表达式的编译表示形式,指定为字符串的正则表达式必须首先被编译为此类的实例
因为该类没有构造函数,可以通过类中的方法获取此类对象。
Static Pattern compile(String regex);//将给定的正则表达式编译到模式中
Matcher matcher(CharSequence input);//创建匹配给定的输入与此模式的匹配器
Mactcher类引擎或匹配器,通过解释Pattern,执行匹配操作的引擎。
Macther类中的常用方法:
Boolean find();//尝试查找与该模式匹配的输入序列的下一个子序列
String group();//返回有以前匹配操作所匹配的输入子序列。
说明:
其实String类中的matchers方法,用的就是Pattern和Macther对象来完成的,
只不过被String的方法封装后,用起来简单且功能也单一。
示例:
- import java.util.regex.*;
- class Demo2{
- public static void main(String[] args) {
- getDemo();
- }
- public static void getDemo(){
- String str = "jin tian jiu shi di er shi wu tian";
- String reg = "\\b[a-z]{3}\\b";//匹配规则,获取三个字母组成的单词.同时还需用到单词边界匹配器\b
- //将规则封装成对象
- Pattern p = Pattern.compile(reg);
- //让正则对象和要作用的字符串相关联,获取匹配器对象。
- Matcher m = p.matcher(str);
- //将规则作用到字符串上并进行符合规则的子串查找
- //boolean b = m.find();找到返回true,反之false;
- //System.out.println(b);
- //获取匹配后的结果,通过while循环,打印出来
- while (m.find()){
- System.out.println(m.group());
- }
- }
- }
对于这四种功能什么时候该用哪一个呢?或者那几个呢?
1, 如果只想知道该字符串是否对或错,就使用匹配macthes
2, 想要将已有的字符串编程另一个字符串,使用替换,replaceAll
3, 想要按照自定的方式将字符串变成多个字符串,就用切割split来获取规则以外的子串
4, 想要拿到符合需求的字符子串,就用获取,获取符合规则的子串。
练习一:
- /*
- 需求:将下面的字符串转换成“我要学编程”
- 我我...要要要要......学学..编编........程程
- */
- class Demo3{
- public static void main(String[] args) {
- String str = "我我...要要要要......学学..编编........程程";
- //先将“..”替换
- str = str.replaceAll("\\.+","");
- //再将多个重复内容变成单个
- str = str.replaceAll("(.)\\1+","$1");
- System.out.println(str);
- }
- }
- /*
- 需求:
- 将ip地址进行地址段顺序的排序。
- 192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.301
- 分析步骤:
- 1,先将所有数前面添0补足最低三位
- 2,将前三位是0的替换
- 3,切割空格
- 4,再将其排序
- */
- import java.util.*;
- class Demo4{
- 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.301";
- str = str.replaceAll("(\\d+)","00$1");//至少保证每段都有三位
- System.out.println(str);
- str = str.replaceAll("0*(\\d{3})","$1");//保证每段只有三位
- System.out.println(str);
- String[] s = str.split(" ");//按照空格切割
- /*
- TreeSet<String> ts = new TreeSet<String>();//把字符数组的元素添加进集合
- for(String ss:s){
- ts.add(ss);
- }
- //从集合取出元素
- for(String s1:ts){
- System.out.println(s1.replaceAll("0*(\\d+)","$1"));//将面多余的0去电
- }
- */
- Arrays.sort(s);//对数组元素进行排序
- //取出元素
- for(String s1:s){
- System.out.println(s1.replaceAll("0*(\\d+)","$1"));//将面多余的0去电
- }
- }
- }
练习三:
- /*
- 需求:对邮件地址进行校验
- */
- class Demo5{
- public static void main(String[] args) {
- String mail = "9823hg@as.com.cn";
- //较为精确匹配
- String reg = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}";
- //简单匹配
- //String reg = "\w+@\w+(\\.\\w+)+";
- System.out.println(mail.matches(reg));
- }
- }