欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java正則表達(dá)式之Pattern類實(shí)例詳解

 更新時(shí)間:2022年01月12日 11:45:04   作者:挖坑埋你  
Pattern類的作用在于編譯正則表達(dá)式后創(chuàng)建一個(gè)匹配模式,下面這篇文章主要給大家介紹了關(guān)于Java正則表達(dá)式之Pattern類的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

這個(gè)系列的文章我們使用以下的順序進(jìn)行講解:

  • Pattern 詳解;
  • Matcher 詳解;
  • 正則表達(dá)式語(yǔ)法詳解。

接下來(lái)先來(lái)介紹 Pattern 類。

在Java中,java.util.regex包定義了正則表達(dá)式使用到的相關(guān)類,其中最主要的兩個(gè)類為:Pattern、Matcher:

  • Pattern 編譯正則表達(dá)式后創(chuàng)建一個(gè)匹配模式;
  • Matcher 使用Pattern實(shí)例提供的正則表達(dá)式對(duì)目標(biāo)字符串進(jìn)行匹配,是真正影響搜索的對(duì)象。。

另加一個(gè)新的例外類,PatternSyntaxException,當(dāng)遇到不合法的搜索模式時(shí),會(huì)拋出例外。

Pattern 概述

聲明:public final class Pattern implements java.io.Serializable

Pattern 類有final修飾,可知他不能被子類繼承。

含義:模式類,正則表達(dá)式的編譯表示形式。

注意:此類的實(shí)例是不可變的,可供多個(gè)并發(fā)線程安全使用。

Pattern 匹配模式(Pattern flags)

compile( )方法有一個(gè)版本,它需要一個(gè)控制正則表達(dá)式的匹配行為的參數(shù):

Pattern Pattern.compile(String regex, int flag)

flag 的取值范圍

字段說(shuō)明
Pattern.UNIX_LINES        unix行模式,大多數(shù)系統(tǒng)的行都是以\n結(jié)尾的,但是少數(shù)系統(tǒng),比如Windows,卻是以\r\n組合來(lái)結(jié)尾的,啟用這個(gè)模式之后,將會(huì)只以\n作為行結(jié)束符,這會(huì)影響到^、$和點(diǎn)號(hào)(點(diǎn)號(hào)匹配換行符)。
        通過(guò)嵌入式標(biāo)志表達(dá)式 (?d) 也可以啟用 Unix 行模式。
Pattern.CASE_INSENSITIVE        默認(rèn)情況下,大小寫不敏感的匹配只適用于US-ASCII字符集。這個(gè)標(biāo)志能讓表達(dá)式忽略大小寫進(jìn)行匹配。要想對(duì)Unicode字符進(jìn)行大小不明感的匹配,只要將UNICODE_CASE與這個(gè)標(biāo)志合起來(lái)就行了。
        通過(guò)嵌入式標(biāo)志表達(dá)式(?i)也可以啟用不區(qū)分大小寫的匹配。
        指定此標(biāo)志可能對(duì)性能產(chǎn)生一些影響。
Pattern.COMMENTS ???????????????        這種模式下,匹配時(shí)會(huì)忽略(正則表達(dá)式里的)空格字符(不是指表達(dá)式里的”//s”,而是指表達(dá)式里的空格,tab,回車之類)和注釋(從#開始,一直到這行結(jié)束)。
        通過(guò)嵌入式標(biāo)志表達(dá)式(?x) 也可以啟用注釋模式。
Pattern.MULTILINE        默認(rèn)情況下,輸入的字符串被看作是一行,即便是這一行中包好了換行符也被看作一行。當(dāng)匹配“^”到“$”之間的內(nèi)容的時(shí)候,整個(gè)輸入被看成一個(gè)一行。啟用多行模式之后,包含換行符的輸入將被自動(dòng)轉(zhuǎn)換成多行,然后進(jìn)行匹配。
        通過(guò)嵌入式標(biāo)志表達(dá)式 (?m) 也可以啟用多行模式。
Pattern.LITERAL        啟用字面值解析模式。
        指定此標(biāo)志后,指定模式的輸入字符串就會(huì)作為字面值字符序列來(lái)對(duì)待。輸入序列中的元字符或轉(zhuǎn)義序列不具有任何特殊意義。
        標(biāo)志 CASE_INSENSITIVE 和 UNICODE_CASE 在與此標(biāo)志一起使用時(shí)將對(duì)匹配產(chǎn)生影響。其他標(biāo)志都變得多余了。
        不存在可以啟用字面值解析的嵌入式標(biāo)志字符。
Pattern.DOTALL        在這種模式中,表達(dá)式 .可以匹配任何字符,包括行結(jié)束符。默認(rèn)情況下,此表達(dá)式不匹配行結(jié)束符。
        通過(guò)嵌入式標(biāo)志表達(dá)式 (?s) 也可以啟用此種模式(s 是 “single-line” 模式的助記符,在 Perl 中也使用它)。
Pattern.UNICODE_CASE        在這個(gè)模式下,如果你還啟用了CASE_INSENSITIVE標(biāo)志,那么它會(huì)對(duì)Unicode字符進(jìn)行大小寫不敏感的匹配。默認(rèn)情況下,大小寫不明感的匹配只適用于US-ASCII字符集。
        指定此標(biāo)志可能對(duì)性能產(chǎn)生影響。
Pattern.CANON_EQ        當(dāng)且僅當(dāng)兩個(gè)字符的正規(guī)分解(canonical decomposition)都完全相同的情況下,才認(rèn)定匹配。比如用了這個(gè)標(biāo)志之后,表達(dá)式a/u030A會(huì)匹配?。默認(rèn)情況下,不考慮規(guī)范相等性(canonical equivalence)。
        指定此標(biāo)志可能對(duì)性能產(chǎn)生影響。

在這些標(biāo)志里面,Pattern.CASE_INSENSITIVE,Pattern.MULTILINE,以及Pattern.COMMENTS是最有用的(其中Pattern.COMMENTS還能幫我們把思路理清楚,并且/或者做文檔)。注意,你可以用在表達(dá)式里插記號(hào)的方式來(lái)啟用絕大多數(shù)的模式。這些記號(hào)就在上面那張表的各個(gè)標(biāo)志的下面。你希望模式從哪里開始啟動(dòng),就在哪里插記號(hào)。

可以用OR (|)運(yùn)算符把這些標(biāo)志配合使用。

代碼示例

多行模式:Pattern.MULTILINE 示例

我測(cè)試了一下,也就是說(shuō)如果沒(méi)有 MULTILINE 標(biāo)志的話, ^ 和 $ 只能匹配輸入序列的開始和結(jié)束;否則,就可以匹配輸入序列內(nèi)部的行結(jié)束符。測(cè)試代碼如下:

import java.util.regex.*;

/**
 * 多行模式
 */
public class ReFlags_MULTILINE {

    public static void main(String[] args) {

        // 注意里面的換行符
        String str = "hello world\r\n" + "hello java\r\n" + "hello java";

        System.out.println("===========匹配字符串開頭(非多行模式)===========");
        Pattern p = Pattern.compile("^hello");
        Matcher m = p.matcher(str);
        while (m.find()) {
            System.out.println(m.group() + "   位置:[" + m.start() + "," + m.end() + "]");
        }

        System.out.println("===========匹配字符串開頭(多行模式)===========");
        p = Pattern.compile("^hello", Pattern.MULTILINE);
        m = p.matcher(str);
        while (m.find()) {
            System.out.println(m.group() + "   位置:[" + m.start() + "," + m.end() + "]");
        }

        System.out.println("===========匹配字符串結(jié)尾(非多行模式)===========");
        p = Pattern.compile("java$");
        m = p.matcher(str);
        while (m.find()) {
            System.out.println(m.group() + "   位置:[" + m.start() + "," + m.end() + "]");
        }

        System.out.println("===========匹配字符串結(jié)尾(多行模式)===========");
        p = Pattern.compile("java$", Pattern.MULTILINE);
        m = p.matcher(str);
        while (m.find()) {
            System.out.println(m.group() + "   位置:[" + m.start() + "," + m.end() + "]");
        }
    }
}

===========匹配字符串開頭(非多行模式)===========
hello   位置:[0,5]
===========匹配字符串開頭(多行模式)===========
hello   位置:[0,5]
hello   位置:[13,18]
hello   位置:[25,30]
===========匹配字符串結(jié)尾(非多行模式)===========
java   位置:[31,35]
===========匹配字符串結(jié)尾(多行模式)===========
java   位置:[19,23]
java   位置:[31,35]

忽略大小寫:Pattern.CASE_INSENSITIVE 示例

有的時(shí)候,需要進(jìn)行忽略大小寫的匹配。該例子實(shí)現(xiàn)匹配攝氏溫度和華氏溫度,對(duì)于以C、c、F和f結(jié)尾的溫度值都能匹配。

import java.util.regex.Pattern;

public class ReFlags_CASE_INSENSITIVE {

    public static void main(String[] args) {


        System.out.println("===========API忽略大小寫===========");
        String moneyRegex = "[+-]?(\\d)+(.(\\d)*)?(\\s)*[CF]";
        Pattern p = Pattern.compile(moneyRegex,Pattern.CASE_INSENSITIVE);

        System.out.println("-3.33c   " + p.matcher("-3.33c").matches());
        System.out.println("-3.33C   " + p.matcher("-3.33C").matches());


        System.out.println("===========不忽略大小寫===========");
        moneyRegex = "[+-]?(\\d)+(.(\\d)*)?(\\s)*[CF]";
        p = Pattern.compile(moneyRegex);

        System.out.println("-3.33c   " + p.matcher("-3.33c").matches());
        System.out.println("-3.33C   " + p.matcher("-3.33C").matches());


        System.out.println("===========正則內(nèi)部忽略大小寫===========");
        moneyRegex = "[+-]?(\\d)+(.(\\d)*)?(\\s)*(?i)[CF]";
        p = Pattern.compile(moneyRegex);

        System.out.println("-3.33c   " + p.matcher("-3.33c").matches());
        System.out.println("-3.33C   " + p.matcher("-3.33C").matches());


        System.out.println("===========內(nèi)部不忽略大小寫===========");
        moneyRegex = "[+-]?(\\d)+(.(\\d)*)?(\\s)*[CF]";
        p = Pattern.compile(moneyRegex);

        System.out.println("-3.33c   " + p.matcher("-3.33c").matches());
        System.out.println("-3.33C   " + p.matcher("-3.33C").matches());
    }
}

===========API忽略大小寫===========
-3.33c   true
-3.33C   true
===========不忽略大小寫===========
-3.33c   false
-3.33C   true
===========正則內(nèi)部忽略大小寫===========
-3.33c   true
-3.33C   true
===========內(nèi)部不忽略大小寫===========
-3.33c   false
-3.33C   true

啟用注釋:Pattern.COMMENTS 示例

啟用注釋,開啟之后,正則表達(dá)式中的空格以及#號(hào)行將被忽略。

import java.util.regex.Pattern;

public class ReFlags_COMMENTS {

    public static void main(String[] args) {

        System.out.println("===========API啟用注釋===========");
        String comments = "    (\\d)+#this is comments.";
        Pattern p = Pattern.compile(comments, Pattern.COMMENTS);
        System.out.println("1234   " + p.matcher("1234").matches());

        System.out.println("===========不啟用注釋===========");
        comments = "    (\\d)+#this is comments.";
        p = Pattern.compile(comments);
        System.out.println("1234   " + p.matcher("1234").matches());

        System.out.println("===========正則啟用注釋===========");
        comments = "(?x)    (\\d)+#this is comments.";
        p = Pattern.compile(comments);
        System.out.println("1234   " + p.matcher("1234").matches());

        System.out.println("===========不啟用注釋===========");
        comments = "    (\\d)+#this is comments.";
        p = Pattern.compile(comments);
        System.out.println("1234   " + p.matcher("1234").matches());

    }
}

===========API啟用注釋===========
1234   true
===========不啟用注釋===========
1234   false
===========正則啟用注釋===========
1234   true
===========不啟用注釋===========
1234   false

可以看到,#號(hào)到行尾的注釋部分和前面的空白字符都被忽略了。正則表達(dá)式內(nèi)置的啟用注釋為(?x)。

啟用 dotall 模式:Pattern.DOTALL 示例

啟用dotall模式,一般情況下,點(diǎn)號(hào)(.)匹配任意字符,但不匹配換行符,啟用這個(gè)模式之后,點(diǎn)號(hào)還能匹配換行符。

import java.util.regex.Pattern;

public class ReFlags_DOTALL {

    public static void main(String[] args) {

        System.out.println("===========API啟用DOTALL===========");
        String dotall = "<xml>(.)*</xml>";
        Pattern p = Pattern.compile(dotall, Pattern.DOTALL);
        System.out.println("<xml>\\r\\n</xml>   " + p.matcher("<xml>\r\n</xml>").matches());

        System.out.println("===========不啟用DOTALL===========");
        dotall = "<xml>(.)*</xml>";
        p = Pattern.compile(dotall);
        System.out.println("<xml>\\r\\n</xml>   " + p.matcher("<xml>\r\n</xml>").matches());

        System.out.println("===========正則啟用DOTALL===========");
        dotall = "(?s)<xml>(.)*</xml>";
        p = Pattern.compile(dotall);
        System.out.println("<xml>\\r\\n</xml>   " + p.matcher("<xml>\r\n</xml>").matches());

        System.out.println("===========不啟用DOTALL===========");
        dotall = "<xml>(.)*</xml>";
        p = Pattern.compile(dotall);
        System.out.println("<xml>\\r\\n</xml>   " + p.matcher("<xml>\r\n</xml>").matches());

    }
}

===========API啟用DOTALL===========
<xml>\r\n</xml>   true
===========不啟用DOTALL===========
<xml>\r\n</xml>   false
===========正則啟用DOTALL===========
<xml>\r\n</xml>   true
===========不啟用DOTALL===========
<xml>\r\n</xml>   false

平白字符模式 模式:Pattern.LITERAL 示例

啟用這個(gè)模式之后,所有元字符、轉(zhuǎn)義字符都被看成普通的字符,不再具有其他意義。

import java.util.regex.Pattern;

public class ReFlags_LITERAL {

    public static void main(String[] args) {

        System.out.println(Pattern.compile("\\d", Pattern.LITERAL).matcher("\\d").matches());// true
        System.out.println(Pattern.compile("\\d", Pattern.LITERAL).matcher("2").matches());// false

        System.out.println(Pattern.compile("(\\d)+", Pattern.LITERAL).matcher("1234").matches());// false
        System.out.println(Pattern.compile("(\\d)+").matcher("1234").matches());// true

        System.out.println(Pattern.compile("(\\d){2,3}", Pattern.LITERAL).matcher("(\\d){2,3}").matches());// true
    }
}

附:貪婪匹配與懶惰匹配

考慮這個(gè)表達(dá)式:a.*b,它將會(huì)匹配最長(zhǎng)的以a開始,以b結(jié)束的字符串。如果用它來(lái)搜索aabab的話,它會(huì)匹配整個(gè)字符串a(chǎn)abab。這被稱為貪婪匹配。

有時(shí),我們更需要懶惰匹配,也就是匹配盡可能少的字符。前面給出的限定符都可以被轉(zhuǎn)化為懶惰匹配模式,只要在它后面加上一個(gè)問(wèn)號(hào)?。這樣.*?就意味著匹配任意數(shù)量的重復(fù),但是在能使整個(gè)匹配成功的前提下使用最少的重復(fù)。

a.*?b匹配最短的,以a開始,以b結(jié)束的字符串。如果把它應(yīng)用于aabab的話,它會(huì)匹配aab和ab。

public static void main(String[] args) {
        String str = "北京市(海淀區(qū))(朝陽(yáng)區(qū))";
        String paternStr = ".*(?=\\()";
        Pattern pattern = Pattern.compile(paternStr);
        Matcher matcher = pattern.matcher(str);
        if (matcher.find()) {
            System.out.println(matcher.group(0));
        }
}

上述方法的輸出為:北京市(海淀區(qū))

public static void main(String[] args) {
        String str = "北京市(海淀區(qū))(朝陽(yáng)區(qū))";
        String paternStr = ".*?(?=\\()";
        Pattern pattern = Pattern.compile(paternStr);
        Matcher matcher = pattern.matcher(str);
        if (matcher.find()) {
            System.out.println(matcher.group(0));
        }
}

上述方法輸出:北京市

總結(jié)

到此這篇關(guān)于Java正則表達(dá)式之Pattern類的文章就介紹到這了,更多相關(guān)Java正則表達(dá)式Pattern類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論