首页 > 其他 > 详细

【程序员技能】正则表达式总结

时间:2015-04-19 19:39:05      阅读:181      评论:0      收藏:0      [点我收藏+]

正则表达式是运用字符串来匹配一系列契合某个语法规矩的字符串

Java中正则表达式首要用到java.util.regex包中的Pattern类和Matcher


首要分为四种类型的正则操作,分别是匹配、更换、切开和获取。


经过一个简略的实例来演示一下正则表达式的便利的地方

  1. class RegexDemo {

  2.     public static void main(String[] args) {

  3.         String number = "18015501550";

  4.         boolean is = isPhoneNumber(number);

  5.         System.out.println(number + (is?"是":"不是") + "手机号");

  6.     }

  7.     /**

  8.      * 验证是不是为手机号

  9.      */

  10.     private static boolean isPhoneNumber(String number) {

  11.         // 长度必须为11位

  12.         if(number.length() != 11) {

  13.             return false;

  14.         }


  15.         // 第一位不为0

  16.         if(number.charAt(0) == ‘0‘) {

  17.             return false;

  18.         }


  19.         // 只能包含数字

  20.         char[] chs = number.toCharArray();

  21.         for(int i=0; i<chs.length; {


    ="">
  22.             if(chs[i] < ‘0‘ || chs[i] > ‘9‘) {

  23.                 return false;

  24.             }

  25.         }

  26.         return true;

  27.     }

  28. }

仿制代码

上面是用普通的办法验证一串字符串是不是为一个合法的手机号码时



假如运用正则表达式来验证,代码只需求一句如下

  1. boolean is = number.matches("[1-9][0-9]{10}");

仿制代码



StringreplaceAll(String, String)是将契合匹配的内容更换为指定内容,也是一种正则表达式。split(String)是一种切开字符串功用,其回来String[],就是切开的分段成果。




正则的根本语法 

尽管开端现已说了正则操作分为四种,分别是匹配、更换、切开和获取,可是实质上都是匹配,如更换则是先匹配到待更换的内容,然后再将其更换掉;相同切开则是先匹配到用于切开的分隔符,然后再将其切开;获取则是匹配到的内容。 
那么正派的根本匹配语法是哪些呢?String的比如现已说明了一些,如[],{}等。

  • []:其表明一个字符,内部能够书写必定的规矩,如[abc]表明这个字符能够使a、b或许c中的一个;[^abc]则表明这个字符不是a,也不是b,也不是c;别的的还有[1-9]、[a-z]、[a-zA-Z]或许[a-d[m-p]]嵌套式的办法,总归[]是一个字符的规矩。

  • {}:其能够作为一些数量的规矩,跟在一个字符的规矩后边,如[1-9]{10}表明[1-9]规矩重复10次,{10,}10次以上,{10,20}10次到20次。

  • ():其表明分组,分组的功用是为了让后边的规矩能够获取前面规矩的成果,运用示例会愈加简略了解,咱们想运用aa、hh、kk作为分隔符,那么咱们应该怎么做?"[a-z][a-z]"?明显不能够,因为后一个字符和前一个字符要有必定的联系,这即是分组的功用地点,()为一个分组,编号会自动从1开端,所以"([a-z])"的编号为1,后一个字符即是分组1,如何写?\编号表明取得编号的成果,因为\需求转义,所以这儿写了两次,代码如下:




  1. class RegexDemo {

  2.     public static void main(String[] args) {

  3.         String str = "1aadswghh,sdlfkksdf";

  4.         // 运用两个接连且相同的字符作为分隔符 aa hh kk

  5.         String[] strs = str.split("([a-z])\\1");

  6.         for(String s : strs) {

  7.             System.out.println(s);

  8.         }

  9.     }

  10. }

  11. // 履行成果为

  12. 1

  13. dswg

  14. ,sdlf

  15. sdf

仿制代码

  • \d:本来和[0-9]的规矩相同,是一种简写办法。

  • +:表明前一个规矩有一个或许多个。

  • *:表明前一个规矩有0个或许多个。

  • 反斜线、转义和引证:反斜线字符 (‘\’) 用于引证转义结构,如上表所界说的,一起还用于引证别的将被解释为非转义结构的字符。因此,表达式 \ 与单个反斜线匹配,而 { 与左括号匹配。在不表明转义结构的任何字母字符前运用反斜线都是过错的;它们是为将来拓展正则表达式言语保存的。能够在非字母字符前运用反斜线,不论该字符是不是非转义结构的一部分。

  • 字符类 
    字符类能够出现在别的字符类中,而且能够包含并集运算符(隐式)和交集运算符 (&&)。并集运算符表明最少包含其某个操作数类中一切字符的类。交集运算符表明包含一起坐落其两个操作数类中一切字符的类。字符类运算符的优先级如下所示,按从最高到最低的顺序排列:


  1. 1     字面值转义     \x 

  2. 2     分组 [...] 

  3. 3     规模 a-z 

  4. 4     并集 [a-e][i-u] 

  5. 5     交集 [a-z&&[aeiou]] 

  6. 留意,元字符的不相同调集实际上坐落字符类的内部,而非字符类的外部。例如,正则表达式 . 在字符类

  7. 内部就失去了其特别含义,而表达式 - 成为了构成元字符的规模。

仿制代码



  • 行完毕符:行完毕符 是一个或两个字符的序列,符号输入字符序列的行完毕。以下代码被辨认为行完毕符:


  1. 新行(换行)符 (‘\n‘)、 

  2. 后边紧跟新行符的回车符 ("\r\n")、 

  3. 独自的回车符 (‘\r‘)、 

  4. 下一行字符 (‘\u0085‘)、 

  5. 行分隔符 (‘\u2028‘) 或 

  6. 阶段分隔符 (‘\u2029)。 

  7. 假如激活 UNIX_LINES 模式,则新行符是仅有辨认的行完毕符。

仿制代码

组和捕获:捕获组能够经过从左到右核算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:

  1. 1     ((A)(B(C))) 

  2. 2     \A 

  3. 3     (B(C)) 

  4. 4     (C)

仿制代码



  • 组零一直代表整个表达式。之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。捕获的子序列稍后能够经过 Back 引证在表达式中运用,也能够在匹配操作完成后从匹配器获取。与组相关的捕获输入一直是与组近来匹配的子序列。假如因为量化的原因再次核算了组,则在第2次核算失利时将保存其曾经捕获的值(假如有的话)例如,将字符串 “aba” 与表达式 (a(b)?)+ 相匹配,会将第二组设置为 “b”。在每个匹配的最初,一切捕获的输入都会被丢掉。以 (?) 最初的组是纯的非捕获 组,它不捕获文本,也不对于组算计进行计数。


四、正则表达式操作

正则表达式的四种操作,除了String类中的简便匹配、更换、切开、获取等操作外,真实的正则操作运用的是Pattern和Matcher,String的内部的一些操作也是运用的这两个类。他们的根本运用格局如下:

  1. import java.util.regex.*;

  2. class RegexDemo {

  3.     public static void main(String[] args) {

  4.         // 获取一个正则表达式封装类

  5.         Pattern pattern = Pattern.compile("[a-z]");

  6.         // 获取匹配器,并指定待匹配内容

  7.         Matcher matcher = pattern.matcher("a");


  8.         // 匹配

  9.         System.out.println(matcher.matches());

  10.         // 重置指针

  11.         matcher.reset();


  12.         // 获取

  13.         System.out.println(matcher.find());


  14.         // 输出一个获取的内容

  15.         System.out.println(matcher.group());

  16.     }

  17. }

仿制代码


通常能够概括为以下过程:

  • 获取正则表达式封装类Pattern p = Pattern.compile(regex)。需求指定一种规矩。

  • 用待匹配的字符串作为参数获取匹配器Matcher,Matcher matcher = p.matcher(str)。

  • 做相应的处理,如判断是不是匹配matcher.matches(),更换matcher.replaceAll(replacement),切开或许获取(凭借find()和group())。

1、匹配

用一个邮箱验证实例来演示一下匹配的操作,[a-zA-Z0-9_]表明接纳字母和数值还有下划线,后边跟一个+表明前面的字符规矩能够使一个或许一个以上,(\\.[a-zA-Z]+)+表明点加上字母,然后分为一组,这个组能够一个或许一个以上如.com.cn,详细代码如下:

  1. import java.util.regex.*;


  • class RegexDemo {


  •     public static void main(String[] args) {

  •         String regex = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";

  •         // 获取一个正则表达式封装类

  •         Pattern pattern = Pattern.compile(regex);

  •         // 获取匹配器,并指定待匹配内容

  •         Matcher matcher = pattern.matcher("abc@163.com");

  •         System.out.println(matcher.matches());

  •     }

  • }

仿制代码


2、更换

先有两个问题,2Fp>

  1. import java.util.regex.*;

  2. import java.util.*;

  3. class RegexDemo {

  4.     public static void main(String[] args) {

  5.         replace1();

  6.         replace2();

  7.     }


  8.     private static void replace1() {

  9.         String str = "我我...我我...我要..要要...要要..."

  10.             + "学学学....学学...编编编...编程..程.程程...程...程";

  11.         // 先将.悉数铲除,然后将叠词成为一个

  12.         str = str.replaceAll("\\.+","").replaceAll("(.)\\1+","$1");

  13.         System.out.println(str);

  14.     }


  15.     private static void replace2() {

  16.         String ips = "192.68.1.254 102.49.23.013 10.0.10.10 2.2.2.2 8.109.90.30";


  17.         // 先将接连的数字前面增加两个0,然后保存后三位

  18.         ips = ips.replaceAll("(\\d+)","00$1").replaceAll("0*(\\d{3})","$1");

  19.         System.out.println(ips);


  20.         // 运用空格分割出每个Ip

  21.         String[] arr = ips.split(" ");


  22.         TreeSettset = new TreeSet();

  23.         for(String s : arr) {

  24.             tset.add(s);

  25.         }

  26.         for(String s : tset) {

  27.             // 将其数字前的0移除

  28.             System.out.println(s.replaceAll("0*(\\d+)","$1"));

  29.         }

  30.     }

  31. }

  32. // 履行成果为

  33. 我要学编程

  34. 192.068.001.254 102.049.023.013 010.000.010.010 002.002.002.002 008.109.090.030

  35. 2.2.2.2

  36. 8.109.90.30

  37. 10.0.10.10

  38. 102.49.23.13

  39. 192.68.1.254

仿制代码


3、切开

切开与获取的功用有必定的重合,获取是获取契合匹配的,而切开则是获取契合匹配以外的内容,通常切开都是运用直接运用String的split(regex)办法,如依照多个空格切开,代码如下:

  1. class RegexDemo {

  2.     public static void main(String[] args) {

  3.         String str = "ada sadasd   asdas   asd as d ad   s";

  4.         // 一个或一个以上的空格为分隔符

  5.         String[] strs = str.split(" +");

  6.         for(String s : strs) {

  7.             System.out.println(s);

  8.         }

  9.     }

  10. }

  11. // 履行成果为

  12. ada

  13. sadasd

  14. asdas

  15. asd

  16. as

  17. d

  18. ad

  19. s

仿制代码


4、获取

从一个文本文件读取内容,然后从中获取邮箱,也能够将其成为从网络页面上获取邮箱的功用,假如同一个邮箱的页面爬虫相同,示例代码如下:

  1. import java.io.*;

  2. import java.util.regex.*;

  3. import java.net.*;

  4. import java.util.*;

  5. class RegexTest {

  6.     public static void main(String[] args) throws Exception {

  7.         // 数据输入

  8.         BufferedReader reader = new BufferedReader(new FileReader("mail.txt"));

  9.         // 邮箱正则表达式

  10.         String regex = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";

  11.         Pattern pattern = Pattern.compile(regex);

  12.         String line = null;

  13.         // 读取数据

  14.         while((line=reader.readLine())!=null) {

  15.             // 获取匹配器

  16.             Matcher matcher = pattern.matcher(line);

  17.             // 找到

  18.             while(matcher.find()) {

  19.                 // 打印找到的邮箱

  20.                 System.out.println(matcher.group());

  21.             }

  22.         }

  23.     }

  24. }

  25. //履行成果为

  26. abc0@sina.com

  27. abc1@sina.com

  28. abc2@sina.com

  29. abc3@sina.com

  30. ab4c@sina.com

  31. abc5@sina.com

  32. abc6@sina.com

  33. abc7@sina.com

  34. abc8@sina.com

  35. abc11@sina.com

  36. abc9@sina.com

  37. abc12@sina.com

  38. abc55@sina.com

  39. abc123@sina.com

  40. abc1234@sina.com

  41. qqq@sina.com

仿制代码


附录

下面列出了一些正则中的特别字符或许规矩。

字符
x字符 x
\反斜线字符
\0n带有八进制值 0 的字符 n (0 <= n <= 7)
\0nn带有八进制值 0 的字符 nn (0 <= n <= 7)
\0mnn带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7)
\xhh带有十六进制值 0x 的字符 hh
\uhhhh带有十六进制值 0x 的字符 hhhh
\t制表符 (‘\u0009’)
\n新行(换行)符 (‘\u000A’)
\r回车符 (‘\u000D’)
\f换页符 (‘\u000C’)
\a报警 (bell) 符 (‘\u0007’)
\e转义符 (‘\u001B’)
\cx对应于 x 的控制符

.

字符类
[abc]a、b 或 c(简略类)
[^abc]任何字符,除了 a、b 或 c(否定)
[a-zA-Z]a 到 z 或 A 到 Z,两端的字母包含在内(规模)
[a-d[m-p]]a 到 d 或 m 到 p:[a-dm-p](并集)
[a-z&&[def]]d、e 或 f(交集)
[a-z&&[^bc]]a 到 z,除了 b 和 c:[ad-z](减去)
[a-z&&[^m-p]]a 到 z,而非 m 到 p:[a-lq-z](减去)

.

预界说字符类
.任何字符(与行完毕符可能匹配也可能不匹配)
\d数字:[0-9]
\D非数字: [^0-9]
\s空白字符:[ \t\n\x0B\f\r]
\S非空白字符:[^\s]
\w单词字符:[a-zA-Z_0-9]
\W非单词字符:[^\w]

.

POSIX 字符类(仅 US-ASCII)
\p{Lower}小写字母字符:[a-z]
\p{Upper}大写字母字符:[A-Z]
\p{ASCII}一切 ASCII:[\x00-\x7F]
\p{Alpha}字母字符:[\p{Lower}\p{Upper}]
\p{Digit}十进制数字:[0-9]
\p{Alnum}字母数字字符:[\p{Alpha}\p{Digit}]
\p{Punct}标点符号:!”#$%&’()*+,-./:;<=>?@[]^_`{
\p{Graph}可见字符:[\p{Alnum}\p{Punct}]
\p{Print}可打印字符:[\p{Graph}\x20]
\p{Blank}空格或制表符:[ \t]
\p{Cntrl}控制字符:[\x00-\x1F\x7F]
\p{XDigit}十六进制数字:[0-9a-fA-F]
\p{Space}空白字符:[ \t\n\x0B\f\r]

.

java.lang.Character 类(简略的 java 字符类型)
\p{javaLowerCase}
\p{javaUpperCase}
\p{javaWhitespace}
\p{javaMirrored}

.

Unicode 块和种类的类
\p{InGreek}Greek 块(简略块)中的字符
\p{Lu}大写字母(简略种类)
\p{Sc}钱银符号
\P{InGreek}一切字符,Greek 块中的在外(否定)
[\p{L}&&[^\p{Lu}]]一切字母,大写字母在外(减去)

.

鸿沟匹配器
^行的最初
$行的完毕
\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 次

.

Reluctant 数量词
X??X,一次或一次也没有
X*?X,零次或屡次
X+?X,一次或屡次
X{n}?X,刚好 n 次
X{n,}?X,最少 n 次
X{n,m}?X,最少 n 次,可是不超越 m 次

.

Possessive 数量词
X?+X,一次或一次也没有
X*+X,零次或屡次
X++X,一次或屡次
X{n}+X,刚好 n 次
X{n,}+X,最少 n 次
X{n,m}+X,最少 n 次,可是不超越 m 次

.

Logical 运算符
XYX 后跟 Y
XY
(X)X,作为捕获组

.

Back 引证
\n任何匹配的 nth 捕获组

特别结构(非捕获)
(?:X)X,作为非捕获组
(?idmsux-idmsux)Nothing,可是将匹配象征i d m s u x on - off
(?idmsux-idmsux:X)X,作为带有给定象征 i d m s u x on - off 的非捕获组 (?=X) X,经过零宽度的正 lookahead
(?!X)X,经过零宽度的负 lookahead
(?<=X)X,经过零宽度的正 lookbehind
(?X,经过零宽度的负 lookbehind
(?>X)X,作为独立的非捕获组


<

 

更多java, java学习,java面试题  http://techfoxbbs.com


【程序员技能】正则表达式总结

原文:http://melorogee.blog.51cto.com/6909056/1635744

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!