正则表达式学习笔记

来源:互联网 发布:linux设置静态ip 编辑:程序博客网 时间:2024/05/20 13:14

这是我的一篇小小学习总结博客,如果有什么欠缺的,希望大神能够指出来。

1、正则表达式 --字符串处理器。

2、正则表达式涉及三个类。

java.lang.String

java.util.regex.Pattern

java.util.regex.Matcher

String类中有几个方法有必要强调一下

matchers方法,这个方法是看指定的字符串是不是匹配一个正则表达式。(对于正则表达式待会下面会有讲到。先记住这个方法。)

public boolean matches(String regex),该方法和Pattern类的静态方法matches方法等效(     public static boolean matches( String regex  ,CharSequence input)   )

(这里浅讲一下CharSequence接口,此接口是一个char值得一个可读序列,它的实现类是CharBuffer,String,StringBuffer,StringBuilder(StringBuilder是一个可变的字符序列,类似于StringBuffer),以此一个方法参数传入的是该接口,那么根据多态性我可以传入实际该接口的类的对象的引用。

 charcharAt(int index)
          返回指定索引的 char 值。 intlength()
          返回此字符序列的长度。 CharSequencesubSequence(int start, int end)
          返回一个新的 CharSequence,它是此序列的子序列。 StringtoString()
          返回一个包含此序列中字符的字符串,该字符串与此序列的顺序相同。这是该接口的几个方法。

(接下来这几个String类的方法只是了解一下就可以了:
public String replaceFirst(String regex, String replacement)该方法是,第一个参数是正则表达式表示的字符串,第二个参数是一个字符串,该字符串要替换掉和第一个参数相匹配的字符串,只是替换掉第一个匹配的字符串,其它的并不替换。
它和此写法等效:Pattern.compile(regex).matcher(str).replaceFirst(repl)

public String replaceAll(String regex,String replacement)此方法是替换掉所有的匹配的字符串。
此方法与Pattern.compile(regex).matcher(str).replaceAll(repl)方法等效。

public String[] split(String regex,int limit)根据匹配给定的正则表达式来拆分此字符串。参数regex是正则表达式的表示形式。
如果limit大于0,那么最多匹配limit-1次
如果limit小于0,那么尽可能多的去匹配。
如果limit等于0,尽可能多的去匹配,而且返回的数组最后一项是空字符串的话会被丢掉。
Regex Limit   结果 :      2      { "boo", "and:foo" } :      5      { "boo", "and", "foo" } :      -2     { "boo", "and", "foo" } o      5      { "b", "", ":and:f", "", "" } o      -2     { "b", "", ":and:f", "", "" } o      0      { "b", "", ":and:f" } 

public String[] split(String regex)该方法和上面的方法类似。只不过是上面方法的默认limit的值是0的情况下。
Regex 结果 :   { "boo", "and", "foo" } o   { "b", "", ":and:f" } 
)

下面让我们来试一试代码吧,看看你能理解多少。

System.out.println("abc".matches("..."));System.out.println("ab23545c".replaceAll("\\d", "*"));Pattern p=Pattern.compile("[a-z]{3}");Matcher m=p.matcher("abc");System.out.println(m.matches());System.out.println("abc".matches("[a-z]{3}"));
输出结果为:
trueab*****ctruetrue

让我们一起进入正则表达式的世界吧!去认识一下正则表达式。

正则表达式深入解析(下面这些式子可以略看一遍,我会在下面有统一的实例讲解。)

字符
x 字符 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} 等效于 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 X 或 Y
(X) X,作为捕获组

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

引用
\ Nothing,但是引用以下字符
\Q Nothing,但是引用所有字符,直到 \E
\E Nothing,但是结束从 \Q 开始的引用

特殊构造(非捕获)
(?:X) X,作为非捕获组
(?idmsux-idmsux) Nothing,但是将匹配标志由 on 转为 off
(?idmsux-idmsux:X) X,作为带有给定标志 on - off 的非捕获组
(?=X) X,通过零宽度的正 lookahead
(?!X) X,通过零宽度的负 lookahead
(?<=X) X,通过零宽度的正 lookbehind
(?<!X) X,通过零宽度的负 lookbehind
(?>X) X,作为独立的非捕获组


首先进入我们    .  *   +   ?  四个正则表达式之旅。


public static void main(String[] args) {p("a".matches("."));//.表示任何字符p("aa".matches("aa"));//p("aaaa".matches("a*"));//a这个字符可能有0次或是多次p("aaaa".matches("a+"));//a这个字符可能有1次或是多次p("".matches("a*"));//p("aaaa".matches("a?"));//a这个字符可能有1次或是0次。p("".matches("a?"));p("a".matches("a?"));p("6461564546646".matches("\\d{3,100}"));//反斜杠表示转译的意思,你只有用两个反斜杠才能表示一个反斜杠的意思,其中\d表示0-9的数字。
大括号表示有3-100个数字。p("192.168.0.aaa".matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"));//如何正确表示一个点,我们知道点在java中表示任何字符,我们需要用一
个反斜杠转译,可是一个反斜杠在java中又不行,所以有填一个反斜杠在转译p("192".matches("[0-2][0-9][0-9]"));//中括号表示范围,[0-9],表示在0-9之间取值。}public static void p(Object o){System.out.println(o);}

运行结果:
truetruetruetruetruefalsetruetruetruefalsetrue

正则表达式的范围:

大家不要将中括号和大括号搞混了,中括号是从这个范围中取值,大括号是表示去多少个值,一个中括号只匹配一个字符。
public static void main(String[] args) {p("a".matches("[abc]"));//注意一个中括号只是匹配一个字符,这句话的意思是我们只匹配abc三个字符中的一个。p("a".matches("[^abc]"));//^表示取反,我们去非abc以外的字符。p("A".matches("[a-zA-Z]"));//-表示从哪个范围到哪个范围,这句是在a-z或是A-Z中取值p("A".matches("[a-z]|[A-Z]"));//|表示或者的意思p("a".matches("[a-z[A-Z]]"));//这个也是表示或者的意思p("R".matches("[A-Z&&[RFG]]"));//这个相当于去交集,就是取两边相交的的那些字符。}public static void p(Object o){System.out.println(o);}
输出结果为:
truefalsetruetruetruetrue

下面我们来认识几个特殊的字符:\s  \w  \d  \

p(" \n\t\r".matches("\\s{4}"));//其中\s表示匹配空白字符p(" ".matches("\\S"));//匹配非空白字符\Sp("a_8".matches("\\w{3}"));//匹配单词字符,上面有。p("abc888%&^&".matches("[a-z]{1,3}\\d+[%^&]+"));p("\\".matches("\\\\"));//这里其实我们是匹配一个反斜杠,正则表达式表示一个反斜杠要用两个反斜杠表示,但是你如果在java中想把这两个反斜杠都}体现出来,那就要用到四个分反斜杠。public static void p(Object o){System.out.println(o);}
truefalsetruetruetrue

下面来看正则表达式关于边界的处理:\b(和\d却分开)

public static void main(String[] args) {p("hello sir".matches("^h.*"));//^表示是以什么开头,以h开头,后面有任意0个或是多个字符。这个要与在中括号里面的^区分开来,那个表示的是非。p("hello sir".matches(".*ir$"));//$是以什么结尾,前面有0个或是多个任意字符,然后后面以ir结尾。p("hello sir".matches("^h[a-z]{1,3}o\\b.*"));//以h开头,任意三个小写英文字母,然后是字母o,接着是单词的边界,接着任意字符0个或是多个。p("hellosir".matches("^h[a-z]{1,3}o\\b.*"));//单词的边界可能是空格,换行,特殊字符等等都算是单词边界。p(" \n".matches("^[\\s&&[^\\n]]*\\n$"));//以空格开头而不是以换行开头。}public static void p(Object o){System.out.println(o);}

运行结果:
truetruetruefalsetrue

首先我们要清楚Pattern类和Mathcer类的区别。

Pattern类表示正则表达式的编译表示形式。我们通过构造Pattern的实例,它的complile方法可以用于返回Pattern实例,这个就类似于一个正则表达式已经被建好了,
我们可以用这个实例(也可以说是正则表达式经过编译后的表现模式)来构造Matcher这个匹配器,专门用于匹配(判断)Pattern这个正则表达式的表现形式和指定字符串。
Pattern类中matcher方法返回一个匹配器(Matcher实例),该方法还指定了字符串(public Matcher matcher(CharSequence input))
其实Pattern中也有一个方法可以用于匹配字符串,但是毕竟就是一个方法,而Matcher毕竟是专业的,方法更多更加有用。
public static void main(String[] args) {p("asdfdf.dfd-sdf@dfsdf-df.com".matches("\\w[[.-]|[\\w]]*@[[.-]|[\\w]]*"));Pattern p=Pattern.compile("\\d{3,5}");String s="123-34345-234-00";Matcher m=p.matcher(s);p(m.matches());//尝试将整个区域与模式匹配m.reset();//重置匹配器。p(m.find());//这个方法是匹配子字符串,如果前面有一个子字符串相匹配了以后,返回true,接着就相当于把这一截去掉了,下次在调用这个方法的时候再从后半截开始匹配p(m.find());//除非是调用了reset重置方法。p(m.find());p(m.find());p(m.lookingAt());//与 matches 方法类似,此方法始终从区域的开头开始;与之不同的是,它不需要匹配整个区域。p(m.lookingAt());p(m.lookingAt());p(m.lookingAt());}public static void p(boolean o){System.out.println(o);}
运行结果:
truefalsetruetruetruefalsetruetruetruetrue

说道Matcher,不得不说的方法是start()和end()方法。

想要调用start和end方法(返回值类型是int类型),只有在你找到(匹配)之后才可以调用,不然会报错,也就是说你要在类似于find()方法成功匹配之后在调用这俩方法,这俩方法返回下标,其中end方法返回下标的后一位。

替换:

public static void main(String[] args) {Pattern p=Pattern.compile("java",Pattern.CASE_INSENSITIVE);Matcher m=p.matcher("java Java JAva Java JaVa IloveJAVA youhateJavafsdfsdfsafdsf");StringBuffer str=new StringBuffer();int index=0;while(m.find()){index++;if(index%2==0){m.appendReplacement(str, "java");}else{m.appendReplacement(str, "JAVA");//替换}}m.appendTail(str);//添加尾巴。,不然后面那一截不会被加上去的。p(str);}public static void p(Object o){System.out.println(o);}
运行结果:
JAVA java JAVA java JAVA Ilovejava youhateJAVAfsdfsdfsafdsf

正则表达式分组使用小括号构成的
例如下面这个正则表达式(\\d{3,5})([a-z]{2})
该正则表达式分有两组,比如说我们想找到数字,我们可以调用m.group(1)找到数字,m.group(2)找到字母。
有时正则表达式比较复杂,怎样开出你要找的东西在第几个分组,那我们就看小括号的左括号是第几个。

其实我们在上面的正则表达式中有三个特殊的数量词:Greedy数量词,Reluctant数量词,Possessive数量词。

(它们之间的区别也就是最后一位字符的不一样)

这三种有什么样的区别呢?
比如说正则表达式  ".{3,10}[0-9]"  表示的是任意字符三到十个,然后后面再加上一个数字。
String s="aaaa5bbbb6";
对于上述字符串,如果是使用Greedy数量词的话,它表示贪婪的,就是它会首先一次性拿到十个任意字符,然后看看有没有第十一个,加入有的话看看是不是数字,是数字就再匹配进来,如果没有第十一个字符,那么久看看从之前拿到的十个字符中拿出来一个,看看是不是数字,不是的话就再拿出来一个。直到和正则表达式想匹配。
如果使用Reluctant数量词的话,其中reluctant表示不情愿的,就是这个家伙比较懒,它每次只拿三个字符,也就是最少的,看看第四个是不是数字,是的话就匹配,不是的话就再拿一个字符,一直到匹配为止。
如果是使用Possessive数量词的话,Possessive英文表示占有的,这个家伙也是比较贪婪的,它也是一次性拿到十个字符,但是这个家伙它不吐出来一个字符,如果第十一个字符不是数字,那就匹配不成功。

正则表达式的特殊(非捕获)

正则表达式(.{3}(?=a))表示三个字符后面跟着一个a,但是a不捕获。
String s="444a66b";
那么捕获的是444.
如果要是((?=a).{3}),把那个(?=a)写在前面,就是那个以a打头。
String s="444a66b";
那么捕获的是a66。

"(?!a).{3}"前面不能是a,后面跟着三个字符。
String s="444a66b";
捕获的是444   66b
".{3}(?!a)"前面任意三个字符,后面跟着的不是a。
String s="444a66b";
捕获的是44a   66b

.{3}(?<!a)从后往前数不能是a的
String s="444a66b";
444  a66
.{3}(?<=a)从后往前数是a的,而且还包含a的。放在前面
44a
 (?<=a).{3}从后往前数不包含a的。
String s="444a66b";
捕获的是66b。
(?<!a).{3}从后往前数不是a的
String s="444a66b";
捕获是:444   a66这里不捕获66b,因为66b后面是a。

正则表达式(\\d\\d)\\1
表示前面匹配两个数字,后面那个反斜杠1表示匹配和第一个组一样的。
例如字符串"1212",匹配为true
正则表达式(\\d(\\d))\\2
表示前面匹配两个数字,后面反斜杠2表示匹配和第二个组相同的字符。
例如字符串"122",匹配为true。

java为我们提供了很多的很多字段,其中很重要的是CASE_INSENSITIVE,忽略大小写匹配。

原创粉丝点击