Java基础——正则表达式

Posted 长河落日圆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基础——正则表达式相关的知识,希望对你有一定的参考价值。

一、什么是正则表达式

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表通常被用来检索、替换那些符合某个模式(规则)的文本。

许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Uinx中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“regex”,单数有regexp、regex、复数有regexps、regexes、regexen。

* 代表多个  
?代表一个字符(可以有,可以无)

--图书编号 要么是5个数字,要么是5个数字加上 - 4 个数字,比如 12345 或 12345-0001

\\d{5}(-\\d{4})?
-- abc?匹配谁?  abc, ab
-- a(bc)  匹配谁 abc ,bc   //bc是一个子匹配
**子匹配
圆扩号扩起来的表达式部分为一个子匹配(也叫子表达式),除了可以得到整个表达式匹配的结果外,还可以得到子表达式的匹配结果。使用验证工具,对  a(bc)? 进行验证,输入 abc,得到的结果是) //? 规定前面的出现 0 或 1 次 
位置 0:    abc
位置 1:     bc
多个子表达式匹配的原始内容按照它们在正则表达式模式中从左到右出现的顺序存储在缓冲区中,这种过程称为捕获,圆扩号中的子匹配所捕获的内容可以在整个表达式中位于这个扩号之后的地方被引用,第一个圆扩号(即第一个子匹配) 捕获的内容用 \\1 表示,第二个用 \\2 ,以此类推
-- 匹配两个连续相同的数字 88,  99,   33    //   (\\d)\\1
-- 匹配 5 个连续相同的数字字符  66666    // (\\d)\\1{4}
-- 匹配 1221 , 4664 , 7887, 0220 这样的  //  (\\d)(\\d)\\2\\1
-- 匹配 1225 , 4668,  5887 这样的(和上例不同是这个首尾并不相同)  // \\d(\\d)\\1\\d  
二、javascript 中的 RegExp 对象
每个正则表达式模式都对应一个 RegExp、javascript 中,有两种创建RegExp 实例的方式。
-- 使用 RegExp 对象 new RegExp("pattern"[,"flags"]) 
-- 使用 RegExp 对象的隐式构造函数  /patern/[flags]  var reg=/^\\d{8}$/
注意:   flags 标志字符
-g  用作全局标志   //对文本中所有的匹配都进行,否则最早的
-i  用作忽略大小写
-m  用作多行标志
当使用显示构造函的方式创建 RegExp实例对象的时候,应将原始的正则表达式模式文本中的每个 \\ 都用 \\\\ 来替换,例如,下面两条语句是等价的
var r =new RegExp("\\\\d{5}");  如果用要匹配 \\ 怎么办? 要使用 \\\\\\\\ (四个)
var r=/\\d{5}/;
==RegExp 对象的方法
-- test(str) 是否包含
-- exec(str) 对一个字符串进行搜索,返回一个数组,没找到返回null
-- compile 略
==String 对象中与正则表达式有关的方法
--match
语法格式为 match(regExp) ,与 RegExp 对象的exec 方法类似,返回一个数组。
注意,传给它的参数是一个 RegExp 对象,如果设置了全局标志,它返回的数组内容和 RegExp.exec() 的返回有所不同。返回的数组里面,是一个个的完整匹配,而不是象前者那样,第一个是完整匹配,而其他的是一个个的子匹配结果
--search
语法为 search(regExp)返回第一个匹配的字符串的位置
--replace
replace(regExp,replaceText) 
--split(regExp)
三、正则表达式语法
要灵活运行正则表达式,必须了解其中各种元字符的功能,元字符从功能上大致分为:
1.限定符
2.选择匹配符
3.分组组合和反向引用符
4.特殊字符
5.字符匹配符
6.定位符
== 限定符
1) {n} 规定前面的必须出现n次    // \\d{5},  a{5}
2) {n,} 规定前面的至少出现n次  //  注意 "至少" 这两个字
3) {n,m} 规定出现次数在n 和 m 之间 //注意,不要乱加空格 (n  和  m 都包含)
4) + 规定前面出现的第一个字符或者是扩号扩起来的第一个序列 必须是一次,或多次 // \\d+   -> 9 或 4567
zo+ 不匹配z  匹配 zo ,匹配 zoo   等效于 zo{1,}
5) * 前面出现的可以是任意次
zo* 匹配 z, 匹配 zo ,匹配 zoooo  等效于 zo{0,}
6) ? 前面的内容一次或零次
zo?  匹配 z , 匹配 zo , 不匹配 zoo, 等效于 zo{0,1}
== 选择匹配符
| , 二选一,尽量往大取
cat|dog nice ,匹配的是 cat 和  dog nice
附:(cat|dog) nice 
== 分组组合和反向引用符
分组组合符:将正则表达式中的某一部分内容组合起来的符号,反向引用符:用于匹配前面的分组组合所捕获到的内容的标识符号
1) (pattern)   注意 要匹配字面意义的 ( ,要使用 \\(
2) \\num 这就是反向引用,用于匹配 num 所指定的特定缓冲区中的内容
例如 要匹配连续 5个相同的数字字符 要使用 (\\d)\\1{4}
3){?:pattern}  不会把 pattern 部分当作子匹配,主要用于那种必须过行组合,但又不想让被组合的部分进行子匹配的情况,省缓冲区
例如 this is (a cat) 写成 this is (?:a cat)
4) (?=pattern) 正向预测先行匹配
例如: windows (?=NT|2000) ,只于 windows 2000 或 windows NT 中的 windows匹配而不于 windows 2003 中的windows 匹配 ,注意它匹配的结果 只是windows部分。比如常见的应用 :将全文 windows 2000 或 windows NT 前面的 windows改写成 win,就要用这个方式 replace(/^windows (?=NT|2000)$/,"win");
注意: windows(?=NT|2000) cat  ,在文本 My windows NT cat 中的匹配结果是多少,啥也匹配不着,因为它匹配的是 window cat
5) (?!pattern) 反向预测先行匹配
== 特殊字符
正则表达式中,以反斜框 \\ 后紧根其他转义字符序列来表示原意字符
1 \\xn (这里的n必须是两位)  \\x41 匹配字符A     \\x04 的意义是 \\x04 所给表示的字符后面紧根字符 1
2 \\n 要求 n 是一个1位的8进制数
3 \\nm mn都是一个一位的8过制数
4 \\nml  n是0-3之间的8进制数
5 \\un 匹配unicode码等于n的字符, 比如 \\u00A9 匹配版权号
6 \\cx  例如 \\cM 匹配 Control+M 表示的控制字符,也就是回车符
7 \\f 匹配换页符  等效于 \\x0a 和\\cJ
8 \\n 匹配回车符  等效于 \\x0d 和\\cM
9 \\t 匹配制表符  等效于 \\x09 和 \\cl
10 \\v 匹配垂直制表等   
== 字符匹配符
1) [...] 匹配包含在其中的任意一个字符
例 [ABC] 匹配 A,B,C 中任意一个,注意,如果要包含 [ 要将它放在第一位 ,如果要包含  \\ 要写成 \\\\
2) [^...]      和上面的相反,匹配没有出现的任何字符
例 [^ABC] 只要不是A,或 B,或 C 就行 注意, ^一定要放在前面,否则它就是字面意义上的^
3) [a-z] 匹配指定泛围的  例如 [0-9] = \\d
4) [^a-z] 匹配不在a-z之间的任意字符
5) \\d 任意的数字字符 等效于 [0-9]
6) \\D     \\d 逆运算 等效于 [^0-9]   //逆运算都是大写的
7) \\s 匹配任何的空白字符 (space)
8) \\S 是\\s 的逆运算
9) \\w 等效[a-zA-Z0-9_] 任意的大小写字母,数字,下划线 //注意它不匹配 - ,但匹配 _
10) /W 是\\w的逆运算 等效于[^a-zA-Z0-9_]
11) . 匹配除了 \\n之外的任意字符,要匹配本身,用\\.
var setr="高睿说: 我我..下棋....很.很....厉害";
//第一次,去掉所有的.
str=str.replace(/\\./g,"");
//第二次,去掉重复的字
str=str.replace(/(.)\\1/g,  "$1");
//结果 : 高睿说: 我下棋很厉害

== 定位符     

1) ^ 规定匹配必须发生在目标字符串的开头部分上,必须出现在最前面才有用

例如 ^o 与 ok中的 o 匹配,但于 dog 中的 o 不匹配,,如果设置了RegExp对象实例的

MultiLine 属性, ^ 还会与首行匹配, 即与 \\n 或 \\r 之后的位置匹配

2) $ 匹配目标字符串的结尾位置,必须出现在最后才有定位符的作用

例如 o$ 与 hello 中的 o 匹配 ,但与 ok 中的 o不匹配

3) \\b 匹配一个字(也就是一个单词) 的边界,它包含了字与空格间的位置以及目标字符串的开始和结束等位置

例如  "er\\b" 匹配 never ok 中的er ,但不匹配 verx 中的er

"\\bis\\b" 匹配 this is anicecat isisisdog 中的 is

4) \\B  \\b的逆运算  ,结果与上例相反

//例子

调用 replace(/win/g,"close") 来替换 win a window ,得到 close a closedow

调用 repalce(/\\bwin\\b,"close"/) 得到 close a window

//例子

如果想在一段文本的内容中的每行前面都加上同一个标记文本,只需使用这个标记文本对

^  做全局替换即可

var str= "aaa\\nbbb\\nccc";

alert( str.replace(/^/mg,"#")); 这里的m 指的是多行的意思  

结果:
       #aaa 
       #bbb
        #ccc
 == 附

---- 原义字符

一些元字符不在再表示它原来的字面意义,如果要匹配它们的字面意义,必须使用

\\ 转义

需要进行转义的字符 $  ( * . [ ? \\ / ^ { |

---- 优先级顺序

* 比字符优先级高,比如 ab* 是 b 和 * 组合后,再和前面的 a组合

()比 *优先级高,(ab)* 是a和b组合后,再和* 组合,字符比 | 优先级高,

a|bc 是 bc组合后,再和 a 组合

一些正则表达式模式范例

匹配空行 /^\\s*$/

匹配html标记  /<(\\S+)(\\s[^>]*)?>[\\s\\S]*<\\/\\1\\s*>/

匹配email   /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$/

匹配两个相同相邻的单词 /\\b([a-z]+)\\1\\b/   //例如  CatCat

匹配 ip 地址  /^\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5](\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])){3}$/

\\u4e00-\\u9fa5  表示中文

四、java 中使用正则表达式验证

             //例一 验证手号码
            public static boolean checkPhone(String str){
                boolean result=true;
                
                if(str.length()!=11){
                    result=false;
                    System.out.println("号码长度不正确");
                }
                if(!str.startsWith("1")){
                    result=false;
                    System.out.println("不是以1开头的");
                }
                
                char [] arr=str.toCharArray();
                for(int i=0;i<arr.length;i++){
                    if(!(arr[i]>=\'0\'&&arr[i]<=\'9\')){
                        result=false;
                        System.out.println("含有非法字符");
                        break;
                    }
                }
                return result;
            }    
            
         //例二
            public static boolean checkPhone2(String str){
                boolean result=true;
                try{
                    Long.parseLong(str);
                }
                catch(Exception ex){
                    System.out.println("手机号格式不正确");
                    result=false;
                }
                return result;
            }
        // 例三
        public static boolean checkPhone3(String str){
                String regex="1[3584]\\\\d{9}";
                return str.matches(regex);
        }
     //例四 使用正则表达式进行切割
        public static void splitDemo1(){
            String str="aaa---bbb-------ccc----ddd";
            String [] strList=str.split("-+");
            System.out.println(strList.length);
            for(String s:strList){
                System.out.println(s);
            }
        }
     //例五
     public static void splitDemo2(){
        String str="aaa.bbb.ccc.ddd";
        String [] strList=str.split("\\\\.");
        System.out.println(strList.length);
        for(String s:strList){
            System.out.println(s);
        }
    }
   //例六
    public static void splitDemo3(){
        String str="c:\\\\windows\\\\system32\\\\aa.bmp";
        String [] strList=str.split("\\\\\\\\");
        System.out.println(strList.length);
        for(String s:strList){
            System.out.println(s);
        }
    }
   //例七 替换
    public static void replaceDemo(){
        String str="要1234想办456假证,请联系13503688749或13302564798 或者是 15050020120 或者 257";
        String regex="\\\\d{11}";
        System.out.println(str.replaceAll(regex, "混球"));
    }
  //例八 获取
    public static void getDemo(){
        String str="林花谢了春红大葱葱,太匆匆,好大大葱大葱葱大葱葱葱";
        String regex="大葱葱+";
        
        Pattern pattern=Pattern.compile(regex);
        Matcher matcher=pattern.matcher(str);
        
        while(matcher.find()){
            System.out.println(matcher.group());
        }
    }
  //例九 从网页上获取
  public static void webGetDemo()throws Exception {
        URL url=new URL("http://localhost:8080/book-shop/login.jsp");
        URLConnection conn=url.openConnection();
        
        BufferedReader br=new BufferedReader(new InputStreamReader(conn.getInputStream()));
        
        String regex="[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\\\.[a-zA-Z0-9_-]+)+";
        Pattern pattern =Pattern.compile(regex);
        
        String str=null;
        while((str=br.readLine())!=null){
            Matcher matcher=pattern.matcher(str);
            while(matcher.find()){
                System.out.println(matcher.group());
            }
        }
    }   

 

以上是关于Java基础——正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

JAVA基础之正则表达式

JAVA ----正则表达式基础及相关应用

Java基础学习笔记十三 常用API之正则表达式DateDateFormatCalendar

JAVA正则表达式怎么匹配所有符合要求的子字符串

python 正则表达式 re模块基础

python基础学习(十三)