一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java字符串 正則表達式詳解

Java字符串 正則表達式詳解

2021-12-23 13:01半城抹茶 Java教程

這篇文章主要介紹了java使用正則表達式查找包含的字符串功能,結合具體實例形式分析了java針對字符串匹配查找的相關實現技巧,需要的朋友可以參考下

在日常Java后端開發過程中,免不了對數據字段的解析,自然就少不了對字符串的操作,這其中就包含了正則表達式這一塊的內容,這里面涉及Java包中Pattern類和Macher類,本篇博客就針對這一塊內容和常見的用法進行總結,本博客主要的參考資料是《Java編程思想》第4版。

以一個問題引出本博客的內容。問題是:檢查一個字符串是否以大寫字母開頭,以句號結尾

?
1
2
3
4
String len="^[A-Z].*[\\.]$";
System.out.println("Taaa.".matches(len));//true
System.out.println("taaa.".matches(len));//false
System.out.println("Taaa".matches(len));//false

1.*[\.] 就 是 正 則 表 達 式 , 用 來 匹 配 字 符 串 。 代 表 一 行 的 起 始 , [ A − Z ] 表 是 A 到 Z 任 何 的 字 母 , 就是正則表達式,用來匹配字符串。^代表一行的起始,[A-Z]表是A到Z任何的字母, 就是正則表達式,用來匹配字符串。代表一行的起始,[A−Z]表是A到Z任何的字母,表示的一行的結束。

一、規則表

規則表定義正則表達式該怎么寫。這類東西不需要刻意去記,用的時候去寫就好,用多了自然就記住了。

1.字符

B 指定字符B
\xhh 十六進制為oxhh的字符
\uhhhh 十六進制表示為oxhhhh的Unicode字符
\t 制表符Tab
\n 換行符
\r 回車
\f 換頁
\e 轉義

2.字符類 .

. 任意字符
[abc] 包含a、b和c的任何字符(和a|b|c作用相同)
[^abc] 除了a、b和c之外的任何字符(否定)
[a-zA-Z] 從a到z或從A到Z的任何字符(范圍)
[abc[hij]] 任意a、b、c、h、i和j字符(與a|b|c|h|i|j作用相同)
[a-z&&[hij]] 任意h、i或j
\s 空白符(空格、tab、換行、換頁和回車)
\S 非空白符
\d 數字
\D 非數字
\w 詞字符[a-zA-Z0-9]
\W 非詞字符

3.邊界匹配符

^ 一行的起始
$ 一行的結束
\b 詞的邊界
\B 非詞的邊界
\G 前一個匹配的結束

4.邏輯操作符

XY Y跟在X后面
X|Y X或Y
(X) 捕獲組

5.量詞

貪婪型 勉強型 占有型 如何匹配
X? X?? X?+ 一個或零個X
X* X*? X*+ 零個或多個X
X+ X+? X++ 一個或多個X
X{n} X{n}? X{n}+ 恰好n次X
X{n,} X{n,}? X{n,}+ 至少n次X
X{n,m} X{n,m}? X{n,m}+ X至少n次,且不超過m次

二、Pattern類

1.Pattern類的實例獲取—compile方法

1.下面主要是Pattern類源碼下一些重要的方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private Pattern(String p, int f) {
    pattern = p;
    flags = f;
 
    // to use UNICODE_CASE if UNICODE_CHARACTER_CLASS present
    if ((flags & UNICODE_CHARACTER_CLASS) != 0)
        flags |= UNICODE_CASE;
 
    // Reset group index count
    capturingGroupCount = 1;
    localCount = 0;
 
    if (!pattern.isEmpty()) {
        try {
            compile();
        } catch (StackOverflowError soe) {
            throw error("Stack overflow during pattern compilation");
        }
    } else {
        root = new Start(lastAccept);
        matchRoot = lastAccept;
    }
}

從Pattern類代碼可以看出構造器是私有的,故無法使用new去獲得Pattern類對象實例。

仔細查詢Pattern類下代碼后發現通過靜態方法compile去獲取Pattern類的實例對象。

?
1
2
3
public static Pattern compile(String regex) {
    return new Pattern(regex, 0);
}

通過compile方法生成一個Pattern類實例對象,然后將想要匹配的字段傳入Pattern對象的matcher()方法,matcher()方法會返回生成一個Matcher類實例對象,這個對象也有很多對應的方法。所以Matcher類也是無法通過new去創建一個實例的,而是通過matcher方法

?
1
2
3
4
5
6
7
8
9
10
public Matcher matcher(CharSequence input) {
    if (!compiled) {
        synchronized(this) {
            if (!compiled)
                compile();
        }
    }
    Matcher m = new Matcher(this, input);
    return m;
}
?
1
2
3
4
5
public static boolean matches(String regex, CharSequence input) {
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(input);
    return m.matches();
}

所以之前博客開頭那個問題,也可以用另外兩種方式實現:

方式一:

?
1
2
3
4
Pattern len = Pattern.compile("^[A-Z].*[\\.]$");
Matcher matcher = len.matcher("Taaa.");
boolean matches = matcher.matches();
System.out.println(matches);

當是從源碼中可以看出matches方法是類靜態方法,所以沒必要使用Macher類實例對象來調用方法。可以使用:

方式二:

?
1
System.out.println(Pattern.matches("^[A-Z].*[\\.]$","Taaa."));

2.split方法

下面是Split方法的源碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public String[] split(CharSequence input, int limit) {
    int index = 0;
    boolean matchLimited = limit > 0;
    ArrayList<String> matchList = new ArrayList<>();
    Matcher m = matcher(input);
 
    // Add segments before each match found
    while(m.find()) {
        if (!matchLimited || matchList.size() < limit - 1) {
            if (index == 0 && index == m.start() && m.start() == m.end()) {
                // no empty leading substring included for zero-width match
                // at the beginning of the input char sequence.
                continue;
            }
            String match = input.subSequence(index, m.start()).toString();
            matchList.add(match);
            index = m.end();
        } else if (matchList.size() == limit - 1) { // last one
            String match = input.subSequence(index,
                                             input.length()).toString();
            matchList.add(match);
            index = m.end();
        }
    }
 
    // If no match was found, return this
    if (index == 0)
        return new String[] {input.toString()};
 
    // Add remaining segment
    if (!matchLimited || matchList.size() < limit)
        matchList.add(input.subSequence(index, input.length()).toString());
 
    // Construct result
    int resultSize = matchList.size();
    if (limit == 0)
        while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
            resultSize--;
    String[] result = new String[resultSize];
    return matchList.subList(0, resultSize).toArray(result);
}

方法解析:

input:要拆分的字符序列;

limit:結果閾值;根據指定模式拆分輸入序列。

limit參數作用:

limit參數控制應用模式的次數,從而影響結果數組的長度。

如果 n 大于零,那么模式至多應用 n- 1 次,數組的長度不大于 n,并且數組的最后條目將包含除最后的匹配定界符之外的所有輸入。

如果 n 非正,那么將應用模式的次數不受限制,并且數組可以為任意長度。

如果 n 為零,那么應用模式的次數不受限制,數組可以為任意長度,并且將丟棄尾部空字符串。

詳細講解:假設 input=“boo:and:foo”,匹配符為"o",可知模式最多可應用4次,數組的長度最大為5;

1、當limit=-2時,應用模式的次數不受限制且數組可以為任意長度;推測模式應用4次,數組的長度為5,數組為{“b”,"",":and:f","",""};

2、當limit=2時,模式至多應用1次,數組的長度不大于 2,且第二個元素包含除最后的匹配定界符之外的所有輸入;推測模式應用1次,數組的長度為2,數組為{“b”,“o:and:foo”};

3、當limit=7時,模式至多應用6次,數組的長度不大于 7;推測模式應用4次,數組的長度為5,數組為{“b”,"",":and:f","",""};

4、當limit=0時,應用模式的次數不受限制,數組可以為任意長度,并且將丟棄尾部空字符串;推測模式應用4次,數組的長度為3,數組為{“b”,"",":and:f"}。

這里m.find像迭代器,遍歷輸入字符串

3.Pattern中匹配標記參數

編譯標記 效果
Pattern.CANON_EQ 啟用規范等價。當且僅當兩個字符的“正規分解(canonicaldecomposition)”都完全相同的情況下,才認定匹配。默認情況下,不考慮“規范相等性(canonical equivalence)”。
Pattern.CASE_INSENSITIVE 啟用不區分大小寫的匹配。默認情況下,大小寫不敏感的匹配只適用于US-ASCII字符集。這個標志能讓表達式忽略大小寫進行匹配,要想對Unicode字符進行大小不敏感的匹配,只要將UNICODE_CASE與這個標志合起來就行了。
Pattern.COMMENTS 模式中允許空白和注釋。在這種模式下,匹配時會忽略(正則表達式里的)空格字符(不是指表達式里的“\s”,而是指表達式里的空格,tab,回車之類)。注釋從#開始,一直到這行結束。可以通過嵌入式的標志來啟用Unix行模式。
Pattern.DOTALL 啟用dotall模式。在這種模式下,表達式‘.'可以匹配任意字符,包括表示一行的結束符。默認情況下,表達式‘.'不匹配行的結束符。
Pattern.MULTILINE 啟用多行模式。在這種模式下,‘^'和‘ ' 分 別 匹 配 一 行 的 開 始 和 結 束 。 此 外 , ‘ ' 仍 然 匹 配 字 符 串 的 開 始 , ‘ '分別匹配一行的開始和結束。此外,‘^'仍然匹配字符串的開始,‘ '分別匹配一行的開始和結束。此外,‘'仍然匹配字符串的開始,‘'也匹配字符串的結束。默認情況下,這兩個表達式僅僅匹配字符串的開始和結束。
Pattern.UNICODE_CASE 啟用Unicode感知的大小寫折疊。在這個模式下,如果你還啟用了CASE_INSENSITIVE標志,那么它會對Unicode字符進行大小寫不敏感的匹配。默認情況下,大小寫不敏感的匹配只適用于US-ASCII字符集。
Pattern.UNIX_LINES 啟用Unix行模式。在這個模式下,只有‘\n'才被認作一行的中止,并且與‘.'、‘^'、以及‘$'進行匹配。

Pattern.CASE_INSENSITIVEPattern.COMMENTSPattern.MULTILINE這三個比較常用。

三、Matcher類

對照Matcher構造器源碼,可知構造器將Pattern對象的引用賦于Matcher中變量parentPattern,目標字符串賦于變量text;并創建了數組groups和locals 。

數組groups是組使用的存儲。存儲的是當前匹配的各捕獲組的first和last信息。

groups[0]存儲的是組零的first,groups[1]存儲的是組零的last,groups[2]存儲的是組1的first,groups[3]存儲的是組1的last,依次類推。

Matcher類的方法非常多,這里就不對每個方法的源碼進行詳細的解讀了,后續如果有空會深入研究一下。將常用方法總結如下

方法名 功能作用
public int groupCount() 返回此匹配器中的捕獲組數
public String group() 實際上是調用了group(int group) ,只不過參數是0
public String group(int group) 返回當前查找而獲得的與組匹配的所有子串內容
public int start() 返回當前匹配的子串的第一個字符在目標字符串中的索引位置
public int start(int group) 返回當前匹配的指定組中的子串的第一個字符在目標字符串中的索引位置 。
public int end() 返回當前匹配的子串的最后一個字符的下一個位置在目標字符串中的索引位置 。
public int end(int group) 返回當前匹配的的指定組中的子串的最后一個字符的下一個位置在目標字符串中的索引位置
public boolean find() 在目標字符串里查找下一個匹配子串
public boolean find(int start) 重置此匹配器,然后嘗試查找匹配該模式,從指定的位置開始查找下一個匹配的子串
public int regionStart() 報告此匹配器區域的開始索引。
public int regionEnd() 報告此匹配器區域的結束索引(不包括)。
public Matcher region(int start,int end) 設置此匹配器的區域限制。重置匹配器,然后設置區域,使其從start參數指定的索引開始,到 end參數指定的索引結束(不包括end索引處的字符)。
public boolean lookingAt() 從目標字符串開始位置進行匹配。只有在有匹配且匹配的某一子串中包含目標字符串第一個字符的情況下才會返回true。
public boolean matches() 只有完全匹配時才會返回true。
public Matcher appendReplacement(StringBuffer sb, String replacement) 將當前匹配子串替換為指定字符串,并將從上次匹配結束后到本次匹配結束后之間的字符串添加到一個StringBuffer對象中,最后返回其字符串表示形式。
public StringBuffer appendTail(StringBuffer sb) 將最后一次匹配工作后剩余的字符串添加到一個StringBuffer對象里。
public String replaceAll(String replacement) 將匹配的子串用指定的字符串替換。
public String replaceFirst(String replacement) 將匹配的第一個子串用指定的字符串替換。

 

總結

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注服務器之家的更多內容!

原文鏈接:https://blog.csdn.net/weixin_41938314/article/details/120124014

延伸 · 閱讀

精彩推薦
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
主站蜘蛛池模板: 夫妻性生活免费在线观看 | 美女扒下内裤让男人桶的图片 | 亚洲 日韩 自拍 视频一区 | 好姑娘在线视频观看免费 | 99久久综合给久久精品 | 日本大片免aaa费观看视频 | 西野翔全部作品在线观看 | 国产精品天天影视久久综合网 | 亚洲人成网站在线观看妞妞网 | 国产成人高清亚洲一区91 | 男同精品视频免费观看网站 | 扒开斗罗美女了的胸罩和内裤漫画 | 视频在线视频免费观看 | xxxx性欧美极品另类 | 能看的毛片网站 | 日本免费在线 | 欧美在线播放一区二区 | 96免费精品视频在线 | 日韩精品一区二区三区中文版 | 国产精品激情综合久久 | 国产小视频网站 | 国产午夜一区二区在线观看 | 91麻豆精品国产片在线观看 | h版欧美大片免费观看 | 国产人va在线 | 亚洲一区二区精品推荐 | 日本大片网 | 贰佰麻豆剧果冻传媒一二三区 | 日比免费视频 | 成人性生交小说免费看 | 亚洲精品视频观看 | 干露露视频 性感写真 | 四虎国产精品视频免费看 | 欧美老人与小伙子性生交 | 91视频综合网 | 久久91精品国产91久久户 | 色综合合久久天天综合绕视看 | 亚洲国产免费观看视频 | 女人张开腿让男人桶爽 | 99精品国产成人一区二区在线 | 欧美成人免费观看的 |