Java正则表达式

正则表达式(regular expression):对文字进行模糊匹配的语言,用一些特殊的符号(元字符)来代表某种特征的一组字符以及指定匹配的次数,含有员字符的文本不再表示其特定的文本内容,而是一种由正则表达式指定的文本模式,它可以匹配所有符合这一模式的文本串。类似于操作系统的文件通配符:?、*。?表示任意的一个字符(如data_?:data_1,data_a等)。*表示0个或以上的字符(如data_*:data_、data_1、data_ab、data_2dkj等)。

 

一、正则表达式Java源码

      正则表达式是jdk1.4提出,在软件包java.util.regex中实现。在jdk6中该软件包中包含了5个文件。

1、final class ASCII:Utility class that implements the standard C ctype functionality.

该类定义了元字符的值:

    static final int UPPER    = 0x00000100;
    static final int LOWER   = 0x00000200;
    static final int DIGIT     = 0x00000400;
    static final int SPACE     = 0x00000800;
    static final int PUNCT    = 0x00001000;
    static final int CNTRL    = 0x00002000;
    static final int BLANK    = 0x00004000;
    static final int HEX       = 0x00008000;
    static final int UNDER   = 0x00010000;
    static final int ASCII     = 0x0000FF00;

    static final int ALPHA    = (UPPER|LOWER);

    static final int ALNUM   = (UPPER|LOWER|DIGIT);

    static final int GRAPH   = (PUNCT|UPPER|LOWER|DIGIT);

    static final int WORD    = (UPPER|LOWER|UNDER|DIGIT);

    static final int XDIGIT  = (HEX);

和所有的C类型的字符的整形数组ctype:

private static final int[] ctype = new int[] {
        CNTRL,                  /* 00 (NUL) */
        CNTRL,                  /* 01 (SOH) */
        CNTRL,                  /* 02 (STX) */
        CNTRL,                  /* 03 (ETX) */
        CNTRL,                  /* 04 (EOT) */
        CNTRL,                  /* 05 (ENQ) */
        CNTRL,                  /* 06 (ACK) */
        CNTRL,                  /* 07 (BEL) */
        CNTRL,                  /* 08 (BS)  */
        SPACE+CNTRL+BLANK,      /* 09 (HT)  */
        SPACE+CNTRL,            /* 0A (LF)  */
        SPACE+CNTRL,            /* 0B (VT)  */
        SPACE+CNTRL,            /* 0C (FF)  */
        SPACE+CNTRL,            /* 0D (CR)  */
        CNTRL,                  /* 0E (SI)  */
        CNTRL,                  /* 0F (SO)  */
        CNTRL,                  /* 10 (DLE) */
        CNTRL,                  /* 11 (DC1) */
        CNTRL,                  /* 12 (DC2) */
        CNTRL,                  /* 13 (DC3) */
        CNTRL,                  /* 14 (DC4) */
        CNTRL,                  /* 15 (NAK) */
        CNTRL,                  /* 16 (SYN) */
        CNTRL,                  /* 17 (ETB) */
        CNTRL,                  /* 18 (CAN) */
        CNTRL,                  /* 19 (EM)  */
        CNTRL,                  /* 1A (SUB) */
        CNTRL,                  /* 1B (ESC) */
        CNTRL,                  /* 1C (FS)  */
        CNTRL,                  /* 1D (GS)  */
        CNTRL,                  /* 1E (RS)  */
        CNTRL,                  /* 1F (US)  */
        SPACE+BLANK,            /* 20 SPACE */
        PUNCT,                  /* 21 !     */
        PUNCT,                  /* 22 "     */
        PUNCT,                  /* 23 #     */
        PUNCT,                  /* 24 $     */
        PUNCT,                  /* 25 %     */
        PUNCT,                  /* 26 &     */
        PUNCT,                  /* 27 '     */
        PUNCT,                  /* 28 (     */
        PUNCT,                  /* 29 )     */
        PUNCT,                  /* 2A *     */
        PUNCT,                  /* 2B +     */
        PUNCT,                  /* 2C ,     */
        PUNCT,                  /* 2D -     */
        PUNCT,                  /* 2E .     */
        PUNCT,                  /* 2F /     */
        DIGIT+HEX+0,            /* 30 0     */
        DIGIT+HEX+1,            /* 31 1     */
        DIGIT+HEX+2,            /* 32 2     */
        DIGIT+HEX+3,            /* 33 3     */
        DIGIT+HEX+4,            /* 34 4     */
        DIGIT+HEX+5,            /* 35 5     */
        DIGIT+HEX+6,            /* 36 6     */
        DIGIT+HEX+7,            /* 37 7     */
        DIGIT+HEX+8,            /* 38 8     */
        DIGIT+HEX+9,            /* 39 9     */
        PUNCT,                  /* 3A :     */
        PUNCT,                  /* 3B ;     */
        PUNCT,                  /* 3C <     */
        PUNCT,                  /* 3D =     */
        PUNCT,                  /* 3E >     */
        PUNCT,                  /* 3F ?     */
        PUNCT,                  /* 40 @     */
        UPPER+HEX+10,           /* 41 A     */
        UPPER+HEX+11,           /* 42 B     */
        UPPER+HEX+12,           /* 43 C     */
        UPPER+HEX+13,           /* 44 D     */
        UPPER+HEX+14,           /* 45 E     */
        UPPER+HEX+15,           /* 46 F     */
        UPPER+16,               /* 47 G     */
        UPPER+17,               /* 48 H     */
        UPPER+18,               /* 49 I     */
        UPPER+19,               /* 4A J     */
        UPPER+20,               /* 4B K     */
        UPPER+21,               /* 4C L     */
        UPPER+22,               /* 4D M     */
        UPPER+23,               /* 4E N     */
        UPPER+24,               /* 4F O     */
        UPPER+25,               /* 50 P     */
        UPPER+26,               /* 51 Q     */
        UPPER+27,               /* 52 R     */
        UPPER+28,               /* 53 S     */
        UPPER+29,               /* 54 T     */
        UPPER+30,               /* 55 U     */
        UPPER+31,               /* 56 V     */
        UPPER+32,               /* 57 W     */
        UPPER+33,               /* 58 X     */
        UPPER+34,               /* 59 Y     */
        UPPER+35,               /* 5A Z     */
        PUNCT,                  /* 5B [     */
        PUNCT,                  /* 5C \     */
        PUNCT,                  /* 5D ]     */
        PUNCT,                  /* 5E ^     */
        PUNCT|UNDER,            /* 5F _     */
        PUNCT,                  /* 60 `     */
        LOWER+HEX+10,           /* 61 a     */
        LOWER+HEX+11,           /* 62 b     */
        LOWER+HEX+12,           /* 63 c     */
        LOWER+HEX+13,           /* 64 d     */
        LOWER+HEX+14,           /* 65 e     */
        LOWER+HEX+15,           /* 66 f     */
        LOWER+16,               /* 67 g     */
        LOWER+17,               /* 68 h     */
        LOWER+18,               /* 69 i     */
        LOWER+19,               /* 6A j     */
        LOWER+20,               /* 6B k     */
        LOWER+21,               /* 6C l     */
        LOWER+22,               /* 6D m     */
        LOWER+23,               /* 6E n     */
        LOWER+24,               /* 6F o     */
        LOWER+25,               /* 70 p     */
        LOWER+26,               /* 71 q     */
        LOWER+27,               /* 72 r     */
        LOWER+28,               /* 73 s     */
        LOWER+29,               /* 74 t     */
        LOWER+30,               /* 75 u     */
        LOWER+31,               /* 76 v     */
        LOWER+32,               /* 77 w     */
        LOWER+33,               /* 78 x     */
        LOWER+34,               /* 79 y     */
        LOWER+35,               /* 7A z     */
        PUNCT,                  /* 7B {     */
        PUNCT,                  /* 7C |     */
        PUNCT,                  /* 7D }     */
        PUNCT,                  /* 7E ~     */
        CNTRL,                  /* 7F (DEL) */
    };

ASCII类还定义了一些用于判断是否为特定的元字符类型或者转换为特定的元字符类型:

eg:

static int toUpper(int ch) {
        return isLower(ch) ? (ch - 0x20) : ch;
    }

static int getType(int ch) {
        return ((ch & 0xFFFFFF80) == 0 ? ctype[ch] : 0);
    }

static boolean isType(int ch, int type) {
        return (getType(ch) & type) != 0;
    }

其中isType和getType是基本方法,其他方法很多都是调用isType方法来进行实现的。

eg:static boolean isAlpha(int ch) {
        return isType(ch, ALPHA);
    }

2、public final class Pattern implements java.io.Serializable:A compiled representation of a regular expression。正则表达式的模式定义类。是正则表达式的核心工具类。主要方法:

  1)、compile():Compiles the given regular expression into a pattern.即通过方法给定的字符串参数获取一特定模式Pattern。是一个静态方法,常用Pattern p=Pattern.compile(String pattern)实例化Pattern。

  2)、public String[] split(CharSequence input, int limit):将传入的字符序列和分隔符对字符序列进行分割,并返回一个字符串数组。

  3)、matches():编译给定正则表达式并尝试将给定输入与其匹配.

  4)、public Matcher matcher(CharSequence input):  创建匹配给定输入与此模式的匹配器.

在Pattern类中还定义许多继承于Node的静态类。

3、public interface MatchResult:this interface return  The index of the first character matched。该接口定义了7个方法。

4、public final class Matcher implements MatchResult:该接口不但实现了MatchResult接口定义的7个方法,还实现了许多其他常用的方法。在该类中方法的方法的实现需要Pattern类的方法。该类中的方法主要实现的是在模式匹配后的索引、替换和相关的区域操作等。

5、PatternSyntaxException:定义了一个继承于IllegalArgumentException的异常类来处理模式语法异常。

源码有利于编程能力的提高,同时了解机制的具体实现,增强系统设计思维的提升,应多多查看源码。同时,快速入门时可以选择源码和文档一起使用,在使用正则表达式时,主要参见的是Pattern类的相关文档。

 

二、正则表达式的使用:

正则表达式的使用非常广,主要可以使用在这几方面(当然,对于那些高手来说用处是大大的超过了下面我有限的陈列):

1、字符序列查询,包含子序列的查询和将特定模式的字符序列查询后并提取出来两种常用手段。

查询:String str="abc efg ABC";

  String regEx="a|f"; //表示a或f

  Pattern p=Pattern.compile(regEx);

  Matcher m=p.matcher(str);

  boolean rs=m.find();

如果str中有regEx,那么rs为true,否则为flase。如果想在查找时忽略大小写,则可以写成Pattern p=Pattern.compile(regEx,Pattern.CASE_INSENSITIVE);

 

提取:String regEx=".+\(.+)$";

  String str="c:\dir1\dir2\name.txt";

  Pattern p=Pattern.compile(regEx);

  Matcher m=p.matcher(str);

  boolean rs=m.find();

  for(int i=1;i<=m.groupCount();i++){

  System.out.println(m.group(i));

  }

    以上的执行结果为name.txt,提取的字符串储存在m.group(i)中,其中i最大值为m.groupCount();

2、字符串分割:可将字符序列通过特定分隔符划分为多个字符串。常用split方法返回一个字符串数组。可用于站点和路径分析,信息分割(如二维码名片解码后提取姓名)。

分割:String regEx="::";

  Pattern p=Pattern.compile(regEx);

  String[] r=p.split("xd::abc::cde");

  执行后,r就是{"xd","abc","cde"},其实分割时还有跟简单的方法:

  String str="xd::abc::cde";

  String[] r=str.split("::");

3、字符串替换或删除:将在字符序列中的查询模式匹配处进行替换或删除。多用Matcher类的replaceFirst或replaceAll来进行替换,替换方法中的字符串参数为替换的字符串。删除时替换方法replaceFirst或replaceAll的参数为空字符串。

String regEx="a+"; //表示一个或多个a

  Pattern p=Pattern.compile(regEx);

  Matcher m=p.matcher("aaabbced a ccdeaa");

  String s=m.replaceAll("A");

结果为"Abbced A ccdeA"

如果写成空串,既可达到删除的功能,比如:

String s=m.replaceAll("");

结果为"bbced ccde"

 

三、实例:两个经典的正则表达式的运用:java代码行统计、文件中的邮箱地址抓取

1、下面是一个利用正则表达式计算文件夹下的java文件的代码行数(可检测出空行和注释)。

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class CodeCounter {
 
 static long normalLines = 0;
 static long commentLines = 0;
 static long whiteLines = 0;
 
 public static void main(String[] args) {
  File f = new File("E:\\eclipsejeeworkspace\\RegExp\\src"); //父文件夹
  File[] codeFiles = f.listFiles();                                 //找出父文件夹下的文件
  for(File child : codeFiles){
   if(child.getName().matches(".*\\.java$")) {     //找出其中的Java文件
    parse(child);
   }
  }
  
  System.out.println("normalLines:" + normalLines);
  System.out.println("commentLines:" + commentLines);
  System.out.println("whiteLines:" + whiteLines);
  
 }

 private static void parse(File f) {
  BufferedReader br = null;
  boolean comment = false;
  try {
   br = new BufferedReader(new FileReader(f));
   String line = "";
   while((line = br.readLine()) != null) {
    line = line.trim();
    if(line.matches("^[\\s&&[^\\n]]*$")) {   //空行
     whiteLines ++;
    } else if (line.startsWith("/*") && !line.endsWith("*/")) {
     commentLines ++;
     comment = true; 
    } else if (line.startsWith("/*") && line.endsWith("*/")) {
     commentLines ++;
    } else if (true == comment) {   //true==comment的效率比comment==true的效率高
     commentLines ++;
     if(line.endsWith("*/")) {
      comment = false;
     }
    } else if (line.startsWith("//")) {
     commentLines ++;
    } else {
     normalLines ++;
    }
   }
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  } finally {
   if(br != null) {
    try {
     br.close();
     br = null;
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }
 }

}

2、邮箱地址抓取:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class EmailSpider {

 public static void main(String[] args) {
  try {
   BufferedReader br = new BufferedReader(new FileReader("E:\\eclipsejeeworkspace\\RegExp\\src\\test.htm"));
   //BufferedReader一次可以读取一行数据
   
   String line = "";
   while((line=br.readLine()) != null) {
    parse(line);
   }
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

 private static void parse(String line) {
  Pattern p = Pattern.compile("[\\w[.-]]+@[\\w[.-]]+\\.[\\w]+");//Email地址匹配
  Matcher m = p.matcher(line);
  while(m.find()) {
   System.out.println(m.group());
  }
 }

}

四、附上jdk6的中Pattern中的元字符

构造                        匹配
字符
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] abc(简单类)
[^abc]任何字符,除了 abc(否定)
[a-zA-Z] azAZ,两头的字母包括在内(范围)
[a-d[m-p]] admp[a-dm-p](并集)
[a-z&&[def]] def(交集)
[a-z&&[^bc]] az,除了 bc[ad-z](减去)
[a-z&&[^m-p]] az,而非 mp[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}等效于 java.lang.Character.isLowerCase()
\p{javaUpperCase}等效于 java.lang.Character.isUpperCase()
\p{javaWhitespace}等效于 java.lang.Character.isWhitespace()
\p{javaMirrored}等效于 java.lang.Character.isMirrored()
 
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 运算符
XY X 后跟 Y
X|Y XY
(X) X,作为捕获组
 
Back 引用
\n 任何匹配的 nth捕获组
 
引用
\Nothing,但是引用以下字符
\QNothing,但是引用所有字符,直到 \E
\ENothing,但是结束从 \Q 开始的引用
 
特殊构造(非捕获)
(?: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) X,通过零宽度的负 lookbehind
(?>X) X,作为独立的非捕获组
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前言:本资源来自于javaeye,原资源链接地址:http://www.javaeye.com/topic/67398 原文如下: 以前写了一个java的正规表达式的java工具类,分享一下,有用到的欢迎下载使用。 如果你有常用的定义好的,且测试通过的正规表达式,欢迎跟贴,也让我享用一下 . 类中用到了 jakarta-oro-2.0.jar 包,请大家自己在 apache网站下下载 在这是junit测试单元类我就不提交了,在main()方法中有几个小测试,有兴趣自己玩吧. 这个工具类目前主要有25种正规表达式(有些不常用,但那时才仔细深入的研究了一下正规,写上瘾了,就当时能想到的都写了): 1.匹配图象; 2 匹配email地址; 3 匹配匹配并提取url ; 4 匹配并提取http ; 5.匹配日期 6 匹配电话; 7 匹配身份证 8 匹配邮编代码 9. 不包括特殊字符的匹配 (字符串中不包括符号 数学次方号^ 单引号' 双引号" 分号; 逗号, 帽号: 数学减号- 右尖括号> 左尖括号 0) 12 匹配正整数 13 匹配非正整数(负整数 + 0) 14 匹配负整数; 15. 匹配整数 ; 16 匹配非负浮点数(正浮点数 + 0) 17. 匹配正浮点数 18 匹配非正浮点数(负浮点数 + 0) 19 匹配负浮点数; 20 .匹配浮点数; 21. 匹配由26个英文字母组成的字符串; 22. 匹配由26个英文字母的大写组成的字符串 23 匹配由26个英文字母的小写组成的字符串 24 匹配由数字和26个英文字母组成的字符串; 25 匹配由数字、26个英文字母或者下划线组成的字符串; java源码: /* * Created on 2005-4-15 * * Summary of regular-expression constructs 正则表达式结构简介: * Construct Matches * Characters 字符: * x The character x x 字符 x * \\ The backslash character \\ 反斜杠 * \0n The character with octal value 0n (0 <= n <= 7) \0n 十进制数 (0 <= n <= 7) * \0nn The character with octal value 0nn (0 <= n <= 7) \0nn 十进制数 0nn (0 <= n <= 7) * \0mnn The character with octal value 0mnn (0 <= m <= 3, 0 <= n <= 7) \0mnn 十进制数 0mnn (0 <= m <= 3, 0 <= n <= 7) * \xhh The character with hexadecimal value 0xhh \xhh 十六进制数 0x
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值