java中关于正则一些基础使用

这是本人的第一篇技术型博客,希望能帮到有需要的朋友。-----转载请注明出处。

在之前工作中,需要对很多字符串进行处理。我现在记录下来,以免以后遗忘。

对于正则处理相关的知识,我一开始是从网上找资料配合使用Java API1.6的一个中文版进行学习,很感谢翻译这个版本的团队(机构)或者个人,很感谢那些无私分享自己的知识的朋友。

下文中对于正则的相关知识,现在我是从oracle提供的最新的Java API,可能和以前我看得1.6有些出入,贴出API地址:http://docs.oracle.com/javase/8/docs/api/

一,概括

在Java中,使用java.util.regex包下的Pattern和Matcher类对字符串进行处理。在这其中,其实最为重要还是正则匹配表达式(下文统称正表)的编写。大家可以在写完正表以后再这个网站上测试一下,我就经常在这网站上测试。这是链接:http://tool.oschina.net/regex/

但是有些正则表达式它不能识别,大家最好自己在as或者eclipse上写个单元测试,测试一下。

二,Pattern

该类继承自java.lang.Object类,并且实现了Serializable接口。

该类有两个获取实例的静态方法,分别是compile(String regex)和compile(String regex,int flag)。第二个方法多了个flag,主要用于定制获取的实例的匹配模式。说句题外话建议大家在看API的时候,也打开as或者eclipse,找到相应的类,看里面的源码,这样学习起来更加便捷和直观。

回到正题,API中已经标示出Pattern的Field Summary,标识出来该类有9个常量。如下

CANON_EQ  Enables canonical equivalence.(启用规范的等价,应该是默认的,只匹配)

CASE_INSENSITIVE  Enables case-insensitive matching.(不区分大小写)

COMMENTS  Permits whitespace and comments in pattern.(模式中允许空白和注释)

DOTALL  Enables dotall mode.(这种模式下.匹配行尾)

LITERAL  Enables literal parsing of the pattern.(启动字面量解析模式)

MULTILINE  Enables multiline mode.(多行模式)

UNICODE_CASE  Enables Unicode-aware case folding.(If your code is intended to be portable and uses case-insensitive matching on non-ASCII characters, you should use this flag.)

UNICODE_CHARACTER_CLASS  Enables the Unicode version of Predefined character classes and POSIX character classes.(启用预定义的字符类和POSIX字符类的Unicode版本)

UNIX_LINES  Enables Unix lines mode.(启动Unix的行模式)

当使用Pattern.complie(regex)获取Pattern实例时,由于没有指定flag,系统默认传递了0。其它的就不细说了。对于上面几个flag,在看源码之前我一般都使用Pattern.complie(regex)获取Pattern实例,多行模式的话,在写正表的时候注意一下也是可以匹配多行的。

另使用flag()方法还可以取得当前Pattern实例的模式整数值。

如果只需要判断能否匹配成功,可以调用Pattern.matches(regex,input)。返回true就是匹配成功

三,Matcher

使用Patter的实例patter,调用patter.matcher(CharSequence input),input需要传入实现的CharSequence接口的实参,一般就是字符串。

Matcher中有大量的方法,我只写下少量我用过。

boolean find();是否从下个子序列中找出符合规则的内容。

String group();返回之前的捕获组内容。

String group(int);返回给定组的捕获内容

int gourpCount();返回捕获组的个数

在find()匹配成功一个后,有个类似于指针的东西,移到这个成功捕获的捕获组后面。此时使用group()捕获出来的是指针之前的捕获组内容。我们可以写个单元测试验证一下。

这是输入whatab1whatab2wahtab3whatab4ss,这是正表ab[\d]。匹配的是输入中

下面是方法

 public static String method(String regex, String input) {
        Matcher matcher = Pattern.compile(regex).matcher(input);
        StringBuilder builder = new StringBuilder();
        int i = 0;
        while (matcher.find()) {
            builder.append("这是第").append((++i)).append("组:捕获到【");
            builder.append(matcher.group()).append("】。\n");
        }
        return builder.toString();
    }

输出结果是:

调用方法,参数是
Utils.method("ab[\\d]","whatab1whatab2whatab3whatab4ss")
这是第1组:捕获到【ab1】。
这是第2组:捕获到【ab2】。
这是第3组:捕获到【ab3】。
这是第4组:捕获到【ab4】。  

如果使用group(int),指定具体的匹配位置,需要有多个捕获组,既是"()"。

使用同样的输入,把正表改成.*?(ab([\d])).*?

在Utils的method方法中,分别使用group(),group(0),group(1)和group(2)拼接捕获数组,打印内容如下。

group()打印结果

这是第1组:捕获到【whatab1】。
这是第2组:捕获到【whatab2】。
这是第3组:捕获到【whatab3】。
这是第4组:捕获到【whatab4】。

group(0)打印结果

这是第1组:捕获到【whatab1】。
这是第2组:捕获到【whatab2】。
这是第3组:捕获到【whatab3】。
这是第4组:捕获到【whatab4】。

group(1)打印结果

这是第1组:捕获到【ab1】。
这是第2组:捕获到【ab2】。
这是第3组:捕获到【ab3】。
这是第4组:捕获到【ab4】。

group(2)打印结果

这是第1组:捕获到【1】。
这是第2组:捕获到【2】。
这是第3组:捕获到【3】。
这是第4组:捕获到【4】。

从打印结果我们可以看出,group()和group(0)捕获的内容一致。这里有个特俗情况,如果以"()"将整个正表括起来,那么group(0)和group(1)有什么区别呢?

正表改成(.*?(ab([\d])).*?),下面是打印结果

group(0)和group()

这是第1组:捕获到【whatab1】。
这是第2组:捕获到【whatab2】。
这是第3组:捕获到【whatab3】。
这是第4组:捕获到【whatab4】。

group(1)

这是第1组:捕获到【whatab1】。
这是第2组:捕获到【whatab2】。
这是第3组:捕获到【whatab3】。
这是第4组:捕获到【whatab4】。

group(2)

这是第1组:捕获到【ab1】。
这是第2组:捕获到【ab2】。
这是第3组:捕获到【ab3】。
这是第4组:捕获到【ab4】。

group(3)

这是第1组:捕获到【1】。
这是第2组:捕获到【2】。
这是第3组:捕获到【3】。
这是第4组:捕获到【4】。

如果要捕获"()"里内容,需要注意的是,最好获取一下groupCount()的整型数值,以免没有匹配到该捕获组的内容,导致程序异常。

四,正则表达式

对于正表的编写,首先需要了解其各个符合的含义。

下面是对常用的一些符号进行说明,当然还有绝大部分没有涵盖,大家可以从Java的API中的java.util.regex.Pattern类下查看。

"()":捕获组,在Matcher中已做说明

"[]":匹配范围,注意的是,如果输入[ac]就只匹配a或者c,并不是匹配字符串ac。例如输入,abcac,使用[ac]可以匹配出四组,

  分别是:1.a  2.c  3.a  4.c

"{}":出现次数,有若干写法,{n,m}表示最少出现n次,最多m次,{n}表示出现n次。{n,}表示最少n次。{}一般与[]配合使用,规定[]匹配范围内的字符出现了几次。在这种情况下,有时还会和"|"链接使用。例如XXabXXabXXacXXa1XXdav11 ,使用[abvc]{2}|[a\d]{2}可以匹配出来

ab
ab
ac
a1
av
11

".":一般来说,代表了除空格和其它行尾行首的任何字符(个人理解有误求指出)。

"\d":等价于[0-9],代表0到9的任何数字。

"\D":与\d相反,标示除了\d以外的任意字符

"\w":单词字符

"\W":非单词字符

"\s":空白字符

"\S":非空白字符。在对字符串处理时,如果没有自定多行模式,可将"."替换成"[\\s\\S]"。

"^":如果放置在"[]"里头,表示取其余范围。如"[^a]"表示出了a的任意字符。^也可以表示行首。

"$":表示行尾。

————————————————————————————————————————————————————————

以下三个符号加"{}"在正则表达式中有三种匹配模式,分别是Greedy ,Reluctant 和Possessive ,下面会仔细说区别

"X?":如X?,表示X匹配到一次或者一次也没有。注意的是,在正表后面加个?以后,就成了非贪婪模式。

"X+":如X?,表示X匹配到一次或者多次。

"X*":如X*,表示X匹配到0次或者多次。

"X?"是贪婪模式,会匹配尽可能的内容。"X??"是非贪婪模式,会匹配符合条件的最少的内容。"X?+"是Possessive quantifiers,这个模式我没有用过,也不知道是怎么回事,求分享指导。

——————————————————————————————————————————————————————————

"|":如X|Y,表示匹配X或者Y。

"\Q"和"\E":如\Q|.?\E使得中间的符合失去正则含义,作为普通字符匹配。如ab|.?ab,如果要匹配|.?,需要使用\|\.\?来匹配,但是使用\Q|.?\E就可以直接匹配,不用写那么多转移字符。

"\b":单词边界,如果用来匹配特定单词,可以使用它。如\bregex\b它可以匹配到hello regex!中的regex,但是匹配不到helloregex!中的regex,原因就在于后者的regex不是单词,边界被混杂。

"\B":同"\d"和"\w"将单词变成大写,表示相反的范围。此处表示的是非单词的边界。这玩意儿真心不知道怎么用。试一下。同样的,输入是hello regex!。使用\Be\B,可以匹配到三个e.但是使用\Bregex\B,就匹配不到,因为hello regex!中的regex已经到边界了,把输入改成helloregexs!就可以使用\Bregex\B,匹配到regex。

"\A":表示从输入的开端开始匹配。例如输入"abcdcfg",使用"[\\w]*?c"可以匹配到abc和dc,但是使用"\\A[\\w]*?c"只能匹配到abc。就是因为\A表示从开端开始匹配。

"\G":表示上一次匹配到的结尾。这个真心没用过,求分享,求指导。

"Z"和"z":不知道什么意思,求分享。

"(?=X)":直译是零宽度正向的预测先行。首先这个预测先行,指的是左边的字符,不是右边的字符。如XXabSS,XX是ab的先行,SS是ab的后行。这个东西就匹配在"X"前面的内容。如"XXabcYYabc","[\\s\\S]*?(?=abc)"可以匹配出来XX和YY。API里面的这个解析太特么不好懂了。需要注意的是(?=X)中的X是可以被捕获的。如输入"XabcSabc",匹配"[\\w](?=abc)[\\w]{2}",会匹配出来2个结果,分别是Xab和Sab。

"(?!X)":直译是零宽度的负向预测先行。负个鸡毛,英死早,不会意译。(?=X)表示的是匹配内容右边是X,这个就表示匹配内容的是右边不是X。如输入"XXabcYYabc",正表是"[\\w]{2}(?!X)[\\w]{2}",匹配出来XXab和cYYa。有些朋友可能疑惑,为什么呢?因为XXab前面没有内容,所以可以匹配出来XXab。如果输入不变,将正表换成"[^X]{2}(?!XX)[\\w]{2}",匹配出来的就是abcY和Yabc。

"(?<=X)":直译是零宽度的正向预测后行。表示匹配内容右边的字符串是X。测试一下,输入"XXabcYYabc",正表是"[\\w].*?(?<=abc)",匹配到了"XXabc"和"YYabc"。

"(?<!X)":直译是零宽度的负向预测后行。表示匹配内容右边不是X。测试一下,输入"XXabcYYabc",正表是"[\\w].*?(?<!abc)abc",匹配打印结果如下

这是第1组:捕获到【XXabc】。
这是第2组:捕获到【YYabc】。

第一组中"[\\w].*?(?<!abc)"先捕获到"XX",后面加个"abc"。第二组同理。

"(?>X)":作为一个独立的非捕获组。

五,总结

由于本人水平有限,对于很多东西还未能进行讲解,包括正则匹配时各种模式的匹配原理,包括java.regex.utils包中的其它类的各种方法,包括Pattern类中其它标明的正则符号,文中可能还有很多地方有误,望谅解、望指导。本人对于正则只会点皮毛,希望能帮到需要帮助的朋友。

对于正则表达式的编写,个人认为就是将简单的招式结合在一起,使用以后你会发现它包含着巨大的力量。

 

时间: 2024-10-15 22:26:14

java中关于正则一些基础使用的相关文章

java中的正则操作总结

http://www.cnblogs.com/nerxious/archive/2013/01/03/2842910.html 正则表达式在处理字符串的效率上是相当高的 关于正则表达式的使用,更多的是自己的经验,有兴趣可以参阅相关书籍 这里主要写一下java中的正则操作方法 实例1:匹配 import java.util.Scanner; class Demo { public static void main(String[] args) { Scanner sc = new Scanner(

关于Java中类名.class的基础介绍

声明:文章的总结,来自许多网友的优秀博客 关于通过类名访问class属性,我朋友过好几次了,一直没明白这个东西到底是什么?对此,我参照网友们的博客,总结了一些小知识,如发现错误,希望纠正,谢谢 其实任何一个类,都会有一个Class对象于这个类对应,在这个Class对象中,保存着实例化该类时所需要的基本信息,A.class  其实返回的是一个类A的Class对象,贴一个小代码演示一下: public class Test { /** * @param args */ public static v

Java 中的正则(Pattern)

/**String 中 replaceAll(),matches(),split() 等方法,都是调用Pattern中的方法.学习了,瞬间觉得Pattern强大了 public String replaceAll(String regex, String replacement) { return Pattern.compile(regex).matcher(this).replaceAll(replacement); } public boolean matches(String regex)

2.1号Java复习题目——Java中的字符串(基础知识整理)

Java中的字符串基础知识 作为程序开发当中,使用最频繁的类型之一,字符串有着与基础类型相同的地位,甚至在 JVM(Java 虚拟机)编译的时候会对字符串做特殊的处理,比如拼加操作可能会被 JVM 直接合成为一个最终的字符串,从而到达高效运行的目的. 1 String 特性 String 是标准的不可变类(immutable),对它的任何改动,其实就是创建了一个新对象,再把引用指向该对象: String 对象赋值之后就会在常量池中缓存,如果下次创建会判定常量池是否已经有缓存对象,如果有的话直接返

Java中实现异常处理的基础知识

异常 (Exception):发生于程序执行期间,表明出现了一个非法的运行状况.许多JDK中的方法在检测到非法情况时,都会抛出一个异常对象. 例如:数组越界和被0除. 源代码示例: package yanzheng; //关于异常  2015.11.11 import javax.swing.*; public class AboutException { public static void main(String[] args) { int i=1, j=0, k; //   k=i/j; 

java中使用 正则 抓取邮箱

我们来抓取豆瓣网的邮箱吧!把这个页面的所有邮箱都抓取下来 如https://www.douban.com/group/topic/8845032/: 代码如下: package cn.zhangzong.test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnectio

java中正则表达式(摘自 Nerxious)

正则表达式在处理字符串的效率上是相当高的 关于正则表达式的使用,更多的是自己的经验,有兴趣可以参阅相关书籍 这里主要写一下java中的正则操作方法 实例1:匹配 import java.util.Scanner; class Demo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); //获取输入 System.out.print("Please Enter:"); Strin

Java中常用的异常处理情况课件动手动脑

1:请阅读并运行AboutException.java示例,然后通过后面的几页PPT了解Java中实现异常处理的基础知识. import javax.swing.*; class AboutException { public static void main(String[] a) { int i=1, j=0, k; k=i/j; try { k = i/j; // Causes division-by-zero exception //throw new Exception("Hello.

Java中String的基础知识

Java中String的基础知识 ==与equal的区别 基本数据类型,指的是java中的八种基本数据结构(byte,short,char,int,long,float,double,boolean),一般的比较是使用的 ==,比较的是他们的值. 复合数据类型(类) ==比较的是两个对象的引用,可以理解为在内存中的地址,除非是同一个new出来的对象,他们的 ==为true,否则,都为false. equal是object中的方法.object中的实现如下,内部还是使用==实现,也就是说,如果一个