Java正则表达式1
Posted Lucas小毛驴博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java正则表达式1相关的知识,希望对你有一定的参考价值。
一.正则表达式简介
? 正则表达式,本质上就是字符串,是一种规则,用来匹配,搜索,编辑,操作文本的,java中提供了java.util.regex
包来与正则表达式进行模式匹配。
? 下面以一个简单的例子看看正则表达式,会有个更直观的印象:
public class RegexDemo1 {
public static void main(String[] args) {
Pattern p = Pattern.compile("[0-9]{2,3}");
Matcher m = p.matcher("123");
System.out.println(m.matches());// 输出: true
}
}
? 上述例子中[0-9]{2,3}
就是所谓的正则表达式,{2,3}是匹配由至少2个数字,至多3个数字的字符串,前面[0-9]是指数字0-数字9,也就是十个数字。
? java中提供了java.util.regex
包,包里提供了两个类:Pattern和Matcher
? Pattern就是一种模式,利用它的静态方法compile,编译正则表达式,得到一种匹配的模式,再利用matcher方法进行字符串的匹配,得到匹配结果Matcher,最后由Matcher处理结果。
二.Pattern类和Matcher类
- Pattern类中提供了以下几个常用的方法:
static Pattern compile(String regex)
:将给定的正则表达式编译到模式中。Matcher matcher(CharSequence input)
:创建匹配器,返回Matcher类实例。String[] split(CharSequence input)
:将匹配到的数据拆分。
- Matcher类中提供了以下几个常用的方法:
boolean matches()
:执行匹配验证,当整个匹配时才返回true。String replaceAll(String replacement)
:替换字符串。String group(int group)
:返回指定组的匹配数据。
三.字符串String类对正则的支持
? 字符串String类对正则表达式有四个内置的可以运行正则表达式的方法,分别是:matches(),split() ,replaceAll(),replaceFirst()
? 注意:replace()函数是不支持正则表达式的!
boolean matchers(String regex)
:当且仅当整个字符串匹配时返回true。String[] split(String regex)
:根据给定的正则表达式的匹配来拆分字符串。String replaceAll(String regex, String replacement)
:使用给定的replacement替换字符串所有匹配给定正则表达式的子字符串。String replaceFirst(String regex, String replacement)
:使用给定的replacement替换此字符串匹配给定的正则表达式的第一个子字符串。
public class RegexDemo2 {
public static void main(String[] args) {
String s = "hello java abc";
boolean s1 = s.matches("hello java");
System.out.println(s1);
System.out.println("------------------------");
String[] s2 = s.split("\s");
for (String s0 : s2) {
System.out.println(s0);
}
System.out.println("-------------------------");
String s3 = s.replaceAll("\s", "+");
System.out.println(s3);
System.out.println("-------------------------");
String s4 = s.replaceFirst("\s", "-");
System.out.println(s4);
System.out.println("-------------------------");
}
}
输出结果:
false
------------------------
hello
java
abc
-------------------------
hello+java+abc
-------------------------
hello-java abc
-------------------------
四.正则表达式的规则
常见的匹配符号
.
匹配所有的单个字符,除了换行符。
^regex
匹配以字符串开头
regex$
匹配以字符串结尾
[abc]
复选集定义,匹配字符a,或b,或c
[^abc]
在中括号中插入^符号,表示否定模式
匹配所有的字符,除了a,b,c三个
[a-z1-9]
表示范围的匹配,匹配字母a到z和数字1到9,比如可以匹配到a4
a|b
或的选择,可以匹配a或者b,只会二选一
元字符
d
匹配一个数字,相当于是
[0-9]
的简写,当要匹配一个数字时,可以直接写d,简化了写[0-9]D
匹配一个非数字,相当于是
[^0-9]
的简写s
匹配一个空格,包括tab键( )
S
匹配一个非空格
w
匹配一个单词字符(包括大小写字母,数字,下划线),相当于是
[a-zA-Z0-9_]
的简写W
匹配一个非单词字符(就是除了大小写字母,数字和下划线之外的字符)
限定符
*
:匹配大于等于0个任意字符,可以是0个,也可以是无数个。
比如:X*表示匹配0个或者任意多个字符X,.*则表示匹配任何字符串
+
:匹配大于等于1个任意字符,至少是1个,可以是无数个。
?
:匹配0个或1个任意字符,至少是0个,至多是1个。
{n}
:表示只匹配n个任意字符。
{n,m}
:表示只匹配n-m个任意字符,最少n个,最多m个。
*?
:如果?是限定符*,+,?或者{}后面的第一个字符,那么表示这是一种非贪婪模式
非贪婪模式:就是指尽可能的少匹配,默认的是贪婪模式。
比如
c(.*)b
,默认是贪婪模式,是尽可能多匹配,而.*是匹配任意字个符,那么在匹配caabaabaab时,因为贪婪模式,中间的字符都属于匹配范围,只要最后一个b,最后匹配结果是:caabaabaab而
c(.*?)b
,则是非贪婪匹配,是尽可能少的匹配,所以对于.*,应该是尽快能少的取,所以对于caabaabaab会被匹配,但是匹配得到是caab,中间尽量少匹配字符,所以在遇到第一个b时候结束匹配了。public class RegexDemo3 { public static void main(String[] args) { Pattern p = Pattern.compile("c.*b"); Matcher m = p.matcher("caabaabaab"); if (m.find()) { System.out.println("caabaabaab matches: " + m.group(0)); } // 输出:caabaabaab matches: caabaabaab Pattern p1 = Pattern.compile("c.*?b"); Matcher m1= p1.matcher("caabaabaab"); if (m1.find()) { System.out.println("caabaabaab matches: " + m1.group(0)); }// 输出:caabaabaab matches: caab } }
分组
使用小括号(),可以起到对正则表达式进行分组的作用,这样子我们可以使用Matcher类的group()函数来获取。
分组之后的引用也分为几种:
分组和反向引用
使用分组后会在正则表达式中创建反向引用,反向引用会保存匹配到的字符串片段,后续可以直接通过$来引用,$0表示匹配到的完整模式的字符串,$1表示第一个分组的反向引用,$2表示第二个分组的方向引用,依次类推.......
public class RegexDemo4 { public static void main(String[] args) { // 去除空格,得到Hello,java! String str = "Hello , java !"; String p = "(\w)(\s+)([,!])"; System.out.println(str.replaceAll(p, "$1$3")); // 输出:Hello, java! } }
解析:String p = "(w)(s+)([,!])";
这一个正则表达式分了三个组:
$0 会匹配
(w)(s+)([,!])
的结果,也就是o空格,
和a空格!
$1 会匹配
(w)
的结果,也就是o
和a
$2 会匹配
(s+)
的结果,也就是空格
和空格
$3 会匹配
[,!]
的结果,也就是,
和!
所以在调用replaceAll时,所有匹配到的结果,也就是
o空格,
会被替换为$1$3匹配到的结果o,
,而a空格!
也会被替换为$1$3匹配的结果a!
分组但不反向引用---(?:)
如果我们在小括号内开头加入
?:
,那么这个模式就只是分组,不会创建方向引用。将上面代码做下小修改,如下:
public class RegexDemo4 { public static void main(String[] args) { // 去除空格,得到Hello,java! String str = "Hello , java !"; String p = "(?:\w)(\s+)([,!])"; System.out.println(str.replaceAll(p, "$1$3")); } }
这样子将会报一个错误:
Exception in thread "main" java.lang.IndexOutOfBoundsException: No group 3
因为第一个分组(w)被改为了(?:w),只是分组,不会创建反向引用,所以这时候就没有3个反向引用了,只有两个,所以找不到group 3
分组的反向引用的副本
在使用反向引用时候,也可以不用$去引用,而是使用一个别名,也就是反向引用的副本,只要在小括号中加入?<name>,就会把反向引用保存为一个名字为name的副本了,后续使用时候直接使用name就可以得到反向引用。
public class RegexDemo4 { public static void main(String[] args) { // 去除空格,得到Hello,java! String str = "Hello,java"; Pattern p = Pattern.compile("(?<First>\w*),(?<Second>\w*)"); Matcher m = p.matcher(str); while (m.find()) { System.out.println(m.group(1));// 输出:Hello System.out.println(m.group("First"));// 输出:Hello System.out.println(m.group(2));// 输出:java System.out.println(m.group("Second"));// 输出:java } } }
指定正则表达式的模式
可以在正则表达式语句的开头指定模式,有以下几种模式可以指定:
- (?i):正则表达式忽略大小写。
- (?s):表示单行模式(s表示single),那么正则表达式的.就会匹配所有字符,包括换行符了。
- (?m):表示多行模式(m表示Multi-line),可以使用^和$匹配每一行的开始和结束。
以上是关于Java正则表达式1的主要内容,如果未能解决你的问题,请参考以下文章