xscn

博客园 首页 新随笔 联系 订阅 管理

 

正则表达式

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

给定一个正则表达式和另一个字符串,我们可以达到如下的目的:
1. 给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”);
2. 可以通过正则表达式,从字符串中获取我们想要的特定部分(称作“切割”);
3. 如果regex中有定义组,可以在第二参数中通过$符号获取正则表达式中的已有的组(称作“替换”)。
 
java.util.regex

类 Pattern 正则表达式的编译表示形式。

static Pattern compile(String regex)
将给定的正则表达式编译到模式中。
static Pattern compile(String regex, int flags)
将给定的正则表达式编译到具有给定标志的模式中。
int flags()
返回此模式的匹配标志。
Matcher matcher(CharSequence input)
创建匹配给定输入与此模式的匹配器。
static boolean matches(String regex, CharSequence input)
编译给定正则表达式并尝试将给定输入与其匹配。
String pattern()
返回在其中编译过此模式的正则表达式。
static String quote(String s)
返回指定 String 的字面值模式 String
String[] split(CharSequence input)
围绕此模式的匹配拆分给定输入序列。
String[] split(CharSequence input, int limit)
围绕此模式的匹配拆分给定输入序列。
String toString()
返回此模式的字符串表示形式。
 
java.util.regex

类 Matcher 通过解释 Patterncharacter sequence执行匹配操作的引擎。

Matcher appendReplacement(StringBuffer sb, String replacement)
实现非终端添加和替换步骤。
StringBuffer appendTail(StringBuffer sb)
实现终端添加和替换步骤。
int end()
返回最后匹配字符之后的偏移量。
int end(int group)
返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。
boolean find()
尝试查找与该模式匹配的输入序列的下一个子序列。
boolean find(int start)
重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
String group()
返回由以前匹配操作所匹配的输入子序列。
String group(int group)
返回在以前匹配操作期间由给定组捕获的输入子序列。
int groupCount()
返回此匹配器模式中的捕获组数。
boolean hasAnchoringBounds()
查询此匹配器区域界限的定位。
boolean hasTransparentBounds()
查询此匹配器区域边界的透明度。
boolean hitEnd()
如果匹配器执行的最后匹配操作中搜索引擎遇到输入结尾,则返回 true。
boolean lookingAt()
尝试将从区域开头开始的输入序列与该模式匹配。
boolean matches()
尝试将整个区域与模式匹配。
Pattern pattern()
返回由此匹配器解释的模式。
static String quoteReplacement(String s)
返回指定 String 的字面值替换 String
Matcher region(int start, int end)
设置此匹配器的区域限制。
int regionEnd()
报告此匹配器区域的结束索引(不包括)。
int regionStart()
报告此匹配器区域的开始索引。
String replaceAll(String replacement)
替换模式与给定替换字符串相匹配的输入序列的每个子序列。
String replaceFirst(String replacement)
替换模式与给定替换字符串匹配的输入序列的第一个子序列。
boolean requireEnd()
如果很多输入都可以将正匹配更改为负匹配,则返回 true。
Matcher reset()
重置匹配器。
Matcher reset(CharSequence input)
重置此具有新输入序列的匹配器。
int start()
返回以前匹配的初始索引。
int start(int group)
返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引。
MatchResult toMatchResult()
作为 MatchResult 返回此匹配器的匹配状态。
String toString()
返回匹配器的字符串表示形式。
Matcher useAnchoringBounds(boolean b)
设置匹配器区域界限的定位。
Matcher usePattern(Pattern newPattern)
更改此 Matcher 用于查找匹配项的 Pattern
Matcher useTransparentBounds(boolean b)
设置此匹配器区域边界的透明度。
  
split切割
public String[] split(CharSequence input, int limit)
围绕此模式的匹配拆分给定输入序列。
如果限制 n 大于零,那么模式至多应用 n> - 1 次,数组的长度不大于 n,并且数组的最后条目将包含除最后的匹配定界符之外的所有输入。如果 n 非正,那么将应用模式的次数不受限制,并且数组可以为任意长度。如果 n 为零,那么应用模式的次数不受限制,数组可以为任意长度,并且将丢弃尾部空字符串。
 1 import java.util.regex.*;
 2 import java.util.*;
 3 class  RegexDemo1
 4 {
 5     public static void main(String[] args) 
 6     { 
 7         splitDemo();
 8     }
 9     public static void splitDemo()
10     {
11         String str = "zhangsan...lisi..wangwu....zhaoliu..";
12         String reg = "\\.+";
13         
14         String[] arr1 = str.split(reg);
15 
16         //String[] arr2 = str.split(reg,2);
17         //String[] arr3 = str.split(reg,0);
18         
19         List<String> list = Arrays.asList(arr1);
20         System.out.println(list);
21         System.out.println(list.size());
22     }           
23 }

替换replace

 1 class  RegexDemo2
 2 {
 3     public static void main(String[] args) 
 4     { 
 5         replaceDemo("www13.bai51du2345.com678","\\d{1,}","");
 6         
 7         replaceDemo("affffgthjjjkhjllkeeu","(.)\\1+","@");
 8         
 9         //将叠词替换成$.  //将重叠的字符替换成单个字母。ffff->f
10         replaceDemo("affffgthjjjkhjllkeeu","(.)\\1+","$1");
11     }
12     public static void replaceDemo(String str,String regx,String newstr)
13     {
14         str =str.replaceAll(regx,newstr);
15         System.out.println(str);
16     }           
17

取叠词:

可以将规则封装成一个组。用()完成。组的出现都有编号,从1开始, 想要使用已有的组可以通过  \n(n就是组的编号)的形式来获取。

String str ="sdggdfhhykjjk"

String reg = "(.)\\1";

result:
[sd, df, yk,k]

   
常用匹配格式
构造匹配
 
字符
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]
 
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()
 
边界匹配器
^ 行的开头
$ 行的结尾
\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
 
 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

数量词有Greedy (贪婪)、Reluctant(懒惰)和Possessive(强占)三种:

  1. Greedy是最常用的,它的匹配方式是先把整个字符串吞下,然后匹配整个字符串,如果不匹配,就从右端吐出一个字符,再进行匹配,直到找到匹配或把整个字符串吐完为止。因为总是从最大匹配开始匹配,故称贪婪。
  2. Reluctant正好和Greedy相反,它先从最小匹配开始,先从左端吞入一个字符,然后进行匹配,若不匹配就再吞入一个字符,直到找到匹配或将整个字符串吞入为止。 因为总是从最小匹配开始,故称懒惰。
  3. Possessive和Greedy的匹配方式一样,先把整个字符串吞下,然后匹配整个字符串,如果匹配,就认为匹配,如果不匹配,就认为整个字符串不匹配,它不会从右端吐出一个字符串再进行匹配,只进行一次,故称强占。

数量词的区别以及字符串的获取

 1 import java.util.regex.*;
 2 class  RegexDemo1
 3 {
 4     public static void main(String[] args) 
 5     {           
 6         method();
 7     }
 8         public static void method() {
 9                     
10         Pattern gp = Pattern.compile("1.+a");  //Greedy方式
11         Pattern rp = Pattern.compile("1.+?a");  //Reluctant方式
12         Pattern pp = Pattern.compile("1.++a");  //Possessive方式
13         Matcher gm = gp.matcher("12a34abc"); //Greedy匹配器
14         Matcher rm = rp.matcher("12a34abc"); //Reluctant匹配器
15         Matcher pm = pp.matcher("12a34abc"); //Possessive匹配器
16         
17         if(gm.find()){        
18             System.out.println("Greedy方式----->"+gm.group());
19         }else{
20             System.out.println("Greedy方式找不到匹配值");
21         }
22         
23         if(rm.find()){
24             System.out.println("Reluctant方式----->"+rm.group()); 
25         }else{
26             System.out.println("Reluctant方式找不到匹配值");
27         }
28         
29         if(pm.find()){ 
30             System.out.println("Possessive方式----->"+pm.group());
31         }else{
32             System.out.println("Possessive方式找不到匹配值");
33         }                
34     }    
35 }
36 ---------- 运行 ----------
37 Greedy方式----->12a34a
38 Reluctant方式----->12a
39 Possessive方式找不到匹配值
40 
41 输出完成 (耗时 0 秒) - 正常终止

练习

192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30将ip地址进行地址段顺序的排序。

还按照字符串自然顺序,只要让它们每一段都是3位即可。
    1,按照每一段需要的最多的0进行补齐,那么每一段就会至少保证有3位。
    2,将每一段只保留3位。这样,所有的ip地址都是每一段3位。

 1 import java.util.regex.*;
 2 import java.util.*;
 3 class  RegexDemo3
 4 {
 5     public static void main(String[] args) 
 6     { 
 7         ipDemo();
 8     }    
 9         public static void ipDemo()
10     {
11         String ip = "192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30";
12 
13         ip = ip.replaceAll("(\\d+)","00$1");
14         System.out.println(ip);
15 
16         ip = ip.replaceAll("0*(\\d{3})","$1");
17         System.out.println(ip);
18 
19         String[] arr = ip.split(" ");
20         Arrays.sort(arr);
21         
22         for(String s : arr)
23         {
24             System.out.println(s.replaceAll("0*(\\d+)","$1"));
25         }        
26     } 
27 }           

 

 

 

 

posted on 2013-08-17 17:13  xscn  阅读(265)  评论(0编辑  收藏  举报