Java正则表达式的简单使用

来源:互联网 发布:新疆的网络受限 编辑:程序博客网 时间:2024/05/16 14:32

前言

正则表达式是描述一组字符串的方法,它以这组字符串中的每个字符的共同特征为基础。正则表达式可以用于搜索、编辑、操纵文本与数据。你应该学习一种特殊的语法来创建正则表达式,这种语法已经超出了Java编程语言标准的语法。正则表达式的变化很复杂,不过一旦你理解了它们是如何被构造的话,你就能解释或者创建任意的正则表达式了。
java.util.regex包主要由Pattern、Matcher、 PatternSyntaxException类构成。

Pattern

Pattern对象表示一个已编译的正则表达式。Pattern 类没有提供公共的构造方法,要创建一个Pattern对象,首先必须调用公共的静态 compile 方法。
public static Pattern compile(String regex):将给定的正则表达式编译到Pattern中。
public static Pattern compile(String regex,int flags):将给定的正则表达式编译到具有给定标志的Pattern中。
常用标志如下,(?X)是嵌入到正则表达式的标志字符:
1、Pattern.CASE_INSENSITIVE(?i):默认情况下,大小写不明感的匹配只适用于US-ASCII字符集,这个标志能让表达式忽略大小写进行匹配。要想对Unicode字符进行大小不明感的匹配,只要将UNICODE_CASE与这个标志合起来就行了。例如:Pattern.matches("(?i:Ab)","ab")。
2、Pattern.COMMENTS(?x)在这种模式下,匹配时会忽略正则表达式里的空格字符,不是指表达式里的"\s",而是指表达式里的空格,tab,回车之类。注释从#开始,一直到这行结束。例如:Pattern.matches("(?x:#这行是备注\na b)","ab")。
3、Pattern.DOTALL(?s)在这种模式下,表达式'.'可以匹配任意字符,包括表示一行的结束符,默认不匹配行的结束符。例如:Pattern.matches("(?s:.)","\n")。
4、Pattern.MULTILINE(?m):在这种模式下,'^'和'$'分别匹配一行的开始和结束。此外,'^'仍然匹配字符串的开始,'$'也匹配字符串的结束。默认情况下,这两个表达式仅仅匹配字符串的开始和结束。
5、Pattern.UNICODE_CASE(?u): 在这个模式下,如果你还启用了CASE_INSENSITIVE标志,那么它会对Unicode字符进行大小写不明感的匹配。默认情况下,大小写不明感的匹配只适用于US-ASCII字符集。
6、Pattern.UNIX_LINES(?d): 在这个模式下,只有'\n'才被认作一行的结束,并且与'.','^',以及'$'进行匹配。
7、Pattern.LITERAL:指定此标志后,指定Pattern的输入字符串就会作为字面值字符串来对待,输入字符串中的元字符或转义序列不具有任何特殊意义。 \Q和\E之间的字符串和这个模式作用一样。例如:Pattern.matches("\\Q.*\\E",".*")。

典型的调用顺序是:
Pattern p = Pattern.compile("a*b")
Matcher m = p.matcher("aaaaab")
boolean b = m.matches()

在仅使用一次正则表达式时,可以方便地通过此类定义 matches 方法,此方法编译表达式并在单个调用中将输入序列与其匹配。
boolean b = Pattern.matches("a*b", "aaaaab")

flags方法和pattern方法分别返回已编译的Pattern的标志和正则表达式。

split方法和string类的split方法一样,将给定字符串按照正则表达式拆分成数组。可以带一个参数或者两个参数,第二个参数n默认是0。如果n 大于零,那么模式至多应用 n-1 次,数组的长度不大于 n,并且数组的最后条目将包含除最后的匹配定界符之外的所有输入。如果 n 非正,那么将应用模式的次数不受限制,并且数组可以为任意长度。如果 n 为零,那么应用模式的次数不受限制,数组可以为任意长度,并且将丢弃尾部空字符串。

quote方法返回指定字符串的字面值模式字符串,即返回\Q\E这样的字符串。

Matcher

Matcher是一个解释Pattern和对输入字符串进行匹配操作的引擎。与 Pattern 相似,Matcher 也没有定义公共的构造方法,通过调用 Pattern 对象的matcher方法来获得一个 Matcher 对象:
Pattern pattern = Pattern.compile("abcd");
Matcher matcher = pattern.matcher("abcd");
默认是在整个输入序列中匹配,但是可以调用region方法设置输入序列中的一部分作为匹配区域。Matcher的显式状态包括最近成功匹配的开始和结束索引,由start和end方法获取。它还包括模式中每个捕获组捕获的输入子序列的开始(start(int group索引))和结束(end(int group索引))索引以及该子序列的总数(groupCount方法)。group方法还可以返回每个捕获组捕获的字符串,group(0)始终代表整个匹配,从group(1)开始才是捕获组。groupCount为0代表没有捕获组。Matcher的 reset() 方法重置Matcher,如果需要重新输入序列,则调用其 reset(CharSequence) 方法,重置Matcher将放弃其显式状态信息。
Matcher有三个匹配方法,matches、lookingAt、find,每个方法都返回一个表示成功或失败的布尔值。
matches:和Pattern.matches静态方法一样,将整个输入与正则进行匹配,整个字符串符合正则表达式,才返回true。
lookingAt:将输入从头开始与正则匹配,用来检测字符串的开头部分是否符合正则表达式,如果符合,返回true。
find:从当前位置开始匹配,找到一个匹配的字符串,下次匹配的位置将会变为匹配字符串最后一位的后面。

    public static void main(String[] args) {        Pattern pattern = Pattern.compile("(\\d+)");        Matcher matcher = pattern.matcher("123a4567b90d");        while (matcher.find()) {            System.out.println(matcher.group(1));            System.out.println("匹配到的字符串开始索引:" + matcher.start());            System.out.println("匹配到的字符串结束索引:" + (matcher.end() - 1));        }    }
123匹配到的字符串开始索引:0匹配到的字符串结束索引:24567匹配到的字符串开始索引:4匹配到的字符串结束索引:790匹配到的字符串开始索引:9匹配到的字符串结束索引:10

PatternSyntaxException

对象是一个未检查异常,表示正则表达式的一个语法错误。


构造摘要


行结束符

行结束符 是一个或两个字符的序列,标记输入字符序列的行结尾。以下代码被识别为行结束符:
新行(换行)符 ('\n')
后面紧跟新行符的回车符 ("\r\n")
单独的回车符 ('\r')
下一行字符 ('\u0085')
行分隔符 ('\u2028') 
段落分隔符 ('\u2029)
如果指定 UNIX_LINES(?d)标志,则新行符('\n')是唯一识别的行结束符。 
如果指定 DOTALL 标志,则正则表达式 . 可以与任何字符包括行结束符除外匹配。 
默认情况下,正则表达式 ^ 和 $ 忽略行结束符,仅分别与整个输入序列的开头和结尾匹配。如果指定MULTILINE标志,则 ^ 在输入的开头和行结束符之后发生匹配,$ 在输入的结尾和行结束符之前匹配。

逻辑运算

XY:X 后面跟着 Y
X|Y:X或Y

字符

正则表达式描述例子xx代表的字符Pattern.matches("a", "a")\\反斜杠字符Pattern.matches("\\\\", "\\")\0n8进制值n,Unicode码点等于此值的字符(0 <= n <= 7)Pattern.matches("\\00", (char) 0 + "")\0nn8进制值nn,Unicode码点等于此值的字符(0 <= n <= 7)Pattern.matches("\\061", "1")\0mnn8进制值mnn,Unicode码点等于此值的字符(0 <= m <= 3、0 <= n <= 7)Pattern.matches("\\0377", "ÿ")\xhh16进制值hh,Unicode码点等于此值的字符Pattern.matches("\\x31", "1")\uhhhh16进制值hhhh,Unicode码点等于此值的字符Pattern.matches("\\u597D", "好")\x{h...h}16进制值{h...h},Unicode码点等于此值的字符,支持辅助平面字符Pattern.matches("\\x{597D}", "好")\t制表符 ('\u0009')Pattern.matches("\\u0009", "\t")\n换行符 ('\u000A')Pattern.matches("\\u000A", "\n")\r回车符 ('\u000D')Pattern.matches("\\u000D", "\r")\f换页符 ('\u000C')Pattern.matches("\\u000C", "\f")\a报警符 ('\u0007')Pattern.matches("\\u0007", "\a")\e转义符 ('\u001B')Pattern.matches("\\u001B", "\e")


字符类别

正则表达式描述例子[abc]a,,b 或cPattern.matches("[abc]", "a")[^abc]除a,,b或c之外的任意字符Pattern.matches("[^abc]", "d")[a-zA-Z]a到z或A到ZPattern.matches("[a-zA-Z]", "a")[a-d[m-p]]a到d或m到p,相当于[a-dm-p],并集Pattern.matches("[a-d[m-p]]", "a")[a-z&&[def]]d、e或f,交集Pattern.matches("[a-z&&[def]]", "d")[a-z&&[^bc]]a到z中除了b和c,相当于[ad-z]Pattern.matches("[a-z&&[^bc]]", "d")[a-z&&[^m-p]]a-z中除了m到p,相当于:[a-lq-z]Pattern.matches("[a-z&&[^m-p]]", "d")


预定义字符类别

正则表达式描述.任何字符(与行结束符可能匹配也可能不匹配)\d数字:[0-9]\D非数字: [^\d]\h水平空白字符:[ \t\xA0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000]\H非水平空白字符\s空白字符:[ \t\n\x0B\f\r]\S非空白字符:[^\s]\v垂直空白字符:[\n\x0B\f\r\x85\u2028\u2029]\V非垂直空白字符\w单词字符:[a-zA-Z_0-9]\W非单词字符:[^\w]


边界匹配器

正则表达式描述^匹配行的开头,受多行模式影响$匹配行的结尾,受多行模式影响\b单词边界\B非单词边界
\b:单词和符号之间的边界。
\B:不是\b的边界都属于\B,比如单词和单词的边界,符号和符号的边界。
这里的单词不是\w代表的0-9a-zA-Z_,我猜想应该是w的超集,包括比如汉字、希腊字母、英文字母、数字、下划线等等,符号可以是中文符号、英文符号、空格、制表符、换行符等等,更具体的包括哪些只能在实践中测试。参考下面的例子:
public static void main(String[] args) {          String str = "(我(i ——\t_离";          String rex = "\\b";          Pattern pattern = Pattern.compile(rex);          String[] result = pattern.split(str);          for (String string : result) {              System.out.println("分割的字符串:" + "[" + string + "]");          }      }  
分割的字符串:[(]  分割的字符串:[我]  分割的字符串:[(]  分割的字符串:[i]  分割的字符串:[ —— ]  分割的字符串:[_离]  

public static void main(String[] args) {          String str = "(我(i ——\t_离";          String rex = "\\B";          Pattern pattern = Pattern.compile(rex);          String[] result = pattern.split(str);          for (String string : result) {              System.out.println("分割的字符串:" + "[" + string + "]");          }      }  
分割的字符串:[]  分割的字符串:[(我(i ]  分割的字符串:[—]  分割的字符串:[—]  分割的字符串:[    _]  分割的字符串:[离]  


转义

反斜杠用于引进转义构造,还可以用于引用特殊字符,例如\\代表反斜杠,\(代表左圆括号。


捕获组

捕获组是通过从左到右计算其圆括号来编号的。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:((A)(B(C)))、(A)、(B(C))、(C),组编号0始终代表整个匹配。之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。捕获的子序列稍后可以通过 Back 引用在表达式中使用,也可以在匹配操作完成后调用Matcher类的group方法获取。

非捕获组

非捕获组,它只分组而不捕获文本,也就不占用分组编号,普通非捕获组的语法是(?:X),X是正则表达式构造。

数量词

Greedy

X?   X,一次或一次也没有
X*   X,零次或多次
X+   X,一次或多次
X{n}  X,恰好 n 次
X{n,}   X,至少 n 次
X{n,m}  X,至少 n 次,但是不超过 m 次
public static void main(String[] args) {        Pattern p = Pattern.compile(".{3,10}[0-9]");        String s = "abcd1efgh2";        Matcher m = p.matcher(s);        if (m.find())            System.out.println(m.start() + "-" + m.end());        else            System.out.println("没匹配");    }
输出:0-10
解释:Greedy是尽量吃入后再吐出。这个表达式 {3,10}吃入最多字符的10个字符:abcd1efgh2。吃入之后后面的[0-9]发现没有匹配的,吐出最后一个字符看是数字结果匹配。

Reluctant
X??   X,一次或一次也没有
X*?   X,零次或多次
X+?   X,一次或多次
X{n}?   X,恰好 n 次
X{n,}?   X,至少 n 次
X{n,m}?   X,至少 n 次,但是不超过 m 次
public static void main(String[] args) {        Pattern p = Pattern.compile(".{3,10}?[0-9]");        String s = "abcd1efgh2";        Matcher m = p.matcher(s);        if (m.find())            System.out.println(m.start() + "-" + m.end());        else            System.out.println("没匹配");    }
输出:0-5
解释:对于Reluctant 来说,就是Greedy的一个相反的匹配模式,他从左到有一个一个开始吃入,而不是整个字符串一个一个吐出。这个表达式{3,10}的吞入最少字符的3个字符:abc,吃入之后后面的[0-9]发现没有匹配的,再吃入1个字符后才有匹配。

Possessive
X?+   X,一次或一次也没有
X*+   X,零次或多次
X++   X,一次或多次
X{n}+   X,恰好 n 次
X{n,}+   X,至少 n 次
X{n,m}+   X,至少 n 次,但是不超过 m 次
 public static void main(String[] args) {        Pattern p = Pattern.compile(".{3,10}+[0-9]");        String s = "abcd1efgh2";        Matcher m = p.matcher(s);        if (m.find())            System.out.println(m.start() + "-" + m.end());        else            System.out.println("没匹配");    }
输出:没匹配
它和greedy类似,也是全部吃入,但是唯一不同的是它不吐出。


先行断言和后行断言

先行断言和后行断言其实就是预测之后的字符和之前的字符,只有首先符合预测结果,才能继续匹配,在预测过程中,匹配的位置不会变化,所以被称为“零宽”。例如,预测a后面是bc,那么所有a后面是bc的字符串符合,接着正常匹配,匹配位置依然从a后面开始而不是从c开始。以下4种都属于特殊结构的非捕获组。

(?=pattern) 正向先行断言 :代表字符串中的一个位置,紧接该位置之后的字符序列能够匹配pattern。
例如:Pattern.matches("a(?=b)bc", "abc")返回true。

(?!pattern) 负向先行断言 :代表字符串中的一个位置,紧接该位置之后的字符序列不能匹配pattern。
例如:Pattern.matches("a(?!bcd)bc", "abc")返回true,Pattern.matches("a(?!bc)bc", "abc")返回false。

 (?<=pattern) 正向后行断言 :代表字符串中的一个位置,紧接该位置之前的字符序列能够匹配pattern。
例如:Pattern.matches("a(?<=a)bc", "abc")返回true。

(?<!pattern) 负向后行断言 :代表字符串中的一个位置,紧接该位置之前的字符序列不能匹配pattern。
例如:Pattern.matches("a(?<!ab)bc", "abc")返回true,Pattern.matches("a(?<!a)bc", "abc")返回false。


开启关闭特殊标志

这里的标志就是Pattern类里的区分大小写、多行模式等。Pattern中大部分标志可以使用嵌入式字符串,也可以使用Pattern的常量进行设置。嵌入式字符串直接嵌入在正则表达式里,可以控制开启和关闭、是否捕获。标志前加“-”表示关闭。
(?idmsux-idmsux) :将开启或者关闭标志i d m s u x。
(?idmsux-idmsux:X):将开启或者关闭标志i d m s u x,仅对X有效,但是X是作为非捕获组。
例如:Pattern.matches("(?i)abc(?-i)abc", "aBCabc")返回true,Pattern.matches("(?i)abc(?-i)abc", "aBCaBc")返回false。

0 0
原创粉丝点击