java.util.regex
是一个用正则表达式所订制的模式来对字符串进行匹配工做的类库包。它包括两个类:Pattern
和Matcher
。Pattern是一个正则表达式经编译后的表现模式。Matcher对象是一个状态机器,它依据Pattern对象作为匹配模式对字符串展开匹配检查。 首先一个Pattern实例订制了一个所用语法与PERL的相似的正则表达式经编译后的模式,而后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工做。html
详细摘要请看jdk中文文档,下面我只是列出一些常用的java
构造 | 匹配 |
---|---|
. | 任何字符(与行结束符可能匹配也可能不匹配) |
d | 数字:[0-9] |
D | 非数字: 1 |
s | 空白字符:[ tnx0Bfr] |
S | 非空白字符:2 |
w | 单词字符:[a-zA-Z_0-9] |
W | 非单词字符:3 |
[abc] | a、b 或 c(简单类) |
4 | 任何字符,除了 a、b 或 c(否认) |
[a-zA-Z] | a 到 z 或 A 到 Z,两头的字母包括在内(范围) |
^ | 行的开头 |
$ | 行的结尾 |
X? | X,一次或一次也没有 |
X* | X,零次或屡次 |
X+ | X,一次或屡次 |
X{n} | X,刚好 n 次 |
X{n,} | X,至少 n 次 |
X{n,m} | X,至少 n 次,可是不超过 m 次 |
正则表达式的编译表示形式,学过
python
的都知道这个和python的正则表达式有殊途同归之妙。 可是它的构造方法是私有的,所以不能直接建立对象,可是能够调用它的静态方法返回一个对象,下面会详细介绍python
Pattern
类用于建立一个正则表达式,也能够说建立一个匹配模式,它的构造方法是私有的,不能够直接建立,但能够经过Pattern.complie(String regex)
简单工厂方法建立一个正则表达式,代码以下:正则表达式
//采用的complie(String regex) Pattern pattern = Pattern.compile("\\d+"); //采用的是complie(String regex,int flag)其中flag表示标志,下面的标志表示忽略字母大小写,详细的字段请看文档 Pattern pattern=Pattern.compile("(CHEN)(\\D*)(\\d*)",Pattern.CASE_INSENSITIVE);
Pattern compile(String regex)
用于建立Pattern对象express
Pattern compile(String regex,int flags)
用于建立Pattern对象,而且指定了标志(好比忽略字母大小写)api
int flags()
返回此模式的匹配标志数组
String pattern()
返回在其中编译过此模式的正则表达式。ui
String[] split(CharSequence input)
根据此模式的正则表达式将输入的字符串拆分红String数组,默认的都是所有拆分开.net
//给出正则表达式用于匹配数字(0-9) Pattern pattern = Pattern.compile("\\d+"); String str = "我是陈加兵456郑元梅34擦市场的逻辑啊"; String[] splits = pattern.split(str, 2); //结果:[我是陈加兵,郑元梅34擦市场的逻辑啊]
String[] split(CharSequence input,int limit)
将字符串按照正则表达式表示的内容进行分组,若是limit>0那么就分红limit个组,若是limit<0就按照默认所有分开code
//给出正则表达式用于匹配数字(0-9) Pattern pattern = Pattern.compile("\\d+"); String str = "我是陈加兵456郑元梅34擦市场的逻辑啊"; String[] splits = pattern.split(str, 2); //结果:[我是陈加兵,郑元梅34擦市场的逻辑啊]
Pattern.matches(String regex,CharSequence input)
是一个静态方法,用于快速匹配字符串,该方法适合用于只匹配一次,且匹配所有字符串
Pattern.matches("\\d+","2223");//返回true Pattern.matches("\\d+","2223aa");//返回false,须要匹配到全部字符串才能返回true,这里aa不能匹配到 Pattern.matches("\\d+","22bb23");//返回false,须要匹配到全部字符串才能返回true,这里bb不能匹配到
Matcher matcher(CharSequence input)
建立匹配给定输入与此模式的匹配器,如今只是先了解如下,下面会详细解释Matcher这个类
Pattern p=Pattern.compile("\\d+"); Matcher m=p.matcher("22bb23");
Pattern
类只能作一些简单的匹配操做,要想获得更强更便捷的正则匹配操做,那就须要将Pattern与Matcher一块儿合做.Matcher类提供了对正则表达式的分组支持,以及对正则表达式的屡次匹配支持.
Matcher类和Pattern类同样它的构造方法一样是私有的,所以不能直接构造对象,可是上面咱们说过Pattern类中有一个方法能够返回一个Matcher对象(matcher(CharSequence input)
)
boolean mathces()
尝试将整个区域与模式匹配(针对的是整个字符串,若是整个字符串未彻底匹配,那么返回false,若是彻底匹配那么返回true)
Pattern pattern=Pattern.compile("\\d+"); //建立Pattern对象 String str="I am hreo 1234"; //须要匹配的字符串 Matcher matcher=pattern.matcher(str); //并无彻底匹配,所以返回false,若是str="123445",那么就会返回true System.out.println(matcher.matches());
boolean lookingAt()
尝试从给定字符串的开头开始匹配,若是有子字符串匹配成功,那么返回true(针对的不是整个字符串,而是从开头开始,若是开头有一段字符串匹配成功,那么返回true)
Pattern pattern=Pattern.compile("\\d+"); //建立Pattern对象 String str="1234 I am a hero"; //须要匹配的字符串 Matcher matcher=pattern.matcher(str); //开头的1234匹配到了,所以返回true,若是str="I am a hero 1234"将返回false System.out.println(matcher.lookingAt());
int start()
匹配到的字符串的第一个元素的索引,若是没有匹配到调用此方法将会报错
int end()
匹配到的字符串的最后一个元素的索引,若是没有匹配到调用此方法将会报错
String group()
返回的是匹配到的字符串,若是没有匹配到调用此方法将会报错
Pattern pattern=Pattern.compile("\\d+"); //建立Pattern对象 String str="1234 I am a hero 33455"; //须要匹配的字符串 Matcher matcher=pattern.matcher(str); if(matcher.lookingAt()) { System.out.println("开始匹配到下标为"+matcher.start()); //0 System.out.println("匹配结束的下标为"+matcher.end()); //4 System.out.println("匹配的字符串为"+matcher.group()); //1234 }
boolean find()
查找整个字符串,若是在任意位置有一段字符串可以匹配成功,那么返回true(任意位置),而后若是再次调用这个查找的话,那么就从上次查找到的末尾开始匹配,也就是说查找的是下一个子序列了
Pattern pattern=Pattern.compile("\\d+"); //建立Pattern对象 String str="1234 I am a hero 6666 chenjiabing8888"; //须要匹配的字符串 Matcher matcher=pattern.matcher(str); while(matcher.find()) //若是还有匹配的字符序列 { System.out.println("开始匹配到下标为"+matcher.start()); System.out.println("匹配结束的下标为"+matcher.end()); System.out.println("匹配的字符串为"+matcher.group()); } /*结果以下: * 开始匹配到下标为0 匹配结束的下标为4 匹配的字符串为1234 开始匹配到下标为17 匹配结束的下标为21 匹配的字符串为6666 开始匹配到下标为33 匹配结束的下标为37 匹配的字符串为8888 */ /* * 从上面返回的结果能够知道,find()能够匹配屡次只要这个字符串还有能够匹配, * 而且每次的匹配字段的开始下标都是上一次匹配的结束字母的下一个下标 */
boolean find(int start)
从指定的索引start位置开始匹配,这个用于重置find()匹配器,由于直接使用find()它的每次开始的索引都是不同的
String group(int num)
返回指定分组匹配到的字符串,group(0)表示匹配到的整个字符串,group(1) 表示匹配到的第一个字符(便是第一个括号中匹配的模式)
int groupCount()
返回匹配到的分组个数
String replaceAll(String str)
将全部于模式相匹配的 字符串所有替换程指定的字符串str,返回的是替换后的文本
String replaceFirst(String str)
只将第一次匹配到的字符串替换成指定的字符串str,返回的时替换后的文本
Pattern pattern=Pattern.compile("\\d+"); String str="chenjiabing2344cal3445"; Matcher matcher=pattern.matcher(str); str=matcher.replaceFirst("陈加兵"); System.out.println(str); //输出:chenjiabing陈加兵cal3445 /* * str=matcher.replaceAll("陈加兵"); * System.out.println(str) //输出:chenjiabing陈加兵cal陈加兵 */
捕获组能够经过从左到右计算其开括号来编号,编号是从
1
开始的。例如,在表达式((A)(B(C)))
中,存在四个这样的组:
((A)(B(C))) (A) (B(C)) (C)
总之在正则表达式中在括号中的就是一个分组,下面用一个实例来理解一下
Pattern pattern=Pattern.compile("(\\D*)(\\d+)\\s(\\D+)"); Matcher matcher=pattern.matcher("chenjiabingshizuibangde6666 chenjiabign"); if(matcher.find()) { System.out.println("总共匹配到了"+matcher.groupCount()+"个分组"); System.out.println("匹配到整个字符串为"+matcher.group(0)); System.out.println("匹配到的第一个字符串为"+matcher.group(1)); System.out.println("匹配到的第二个字符串为"+matcher.group(2)); System.out.println("匹配到的第三个字符串为"+matcher.group(3)); }
贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽量多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽量少的匹配
通常写python
爬虫的时候使用的都是非贪婪模式来匹配
使用了贪婪模式后会尽量匹配更多的字符串,便是到了正则表达式定的末尾可是仍是会继续向后匹配,看看是否还能匹配,非贪婪模式则是相反,到了正则表达式定义的结束字符就直接中止匹配了
贪婪模式:.*
,.+
非贪婪模式:.*?
,.+?
//使用了贪婪模式,所以当匹配到第一个</div>的时候还要向后面匹配看看是否还能匹配到,因为后面还有</div>结尾的,所以仍是可以匹配的,所以匹配到的是:陈加兵</div><div>郑元梅 Pattern pattern=Pattern.compile("<div>(.*)</div>"); //使用了非贪婪模式,所以当匹配到第一个</div>的时候就不向后面匹配了,直接返回了,所以匹配到的是:陈加兵 Pattern pattern1=Pattern.compile("<div>(.*?)</div>"); String str="<div>陈加兵</div><div>郑元梅</div>"; Matcher matcher=pattern1.matcher(str); if(matcher.find()) { System.out.println(matcher.groupCount()); //1 System.out.println(matcher.group(1)); //输出匹配到的字符串,此时输出的是:陈加兵,若是使用贪婪模式输出的是:陈加兵</div><div>郑元梅 }