給JAVA程式設計師的正則表達式一課

2020-12-08 蟲蟲搜奇

「不會正則表達式,就算寫遍代碼也嘛不是」。說到正則表達式,可能動態語言的碼農Perl,Python,JS甚至是Golang的開發人員可能都熟悉。對Java碼農來說,可能CURD手到擒來,Spring Stuts Hibernat耳聞能詳,但是說到Regex RE模式,可能熟練的少。

那麼,今天蟲蟲就來給廣大Java碼農來補補正則的課。

正則基礎

正則表達式(Regex,簡稱RE)是一種根據字符串集中的每個字符串的共同特徵來描述字符串集的方法。可用於搜索,編輯或處理文本和數據。簡單來說,正則表達式是幫助我們根據特定格式驗證或匹配字符串的方式。可以類比資料庫的SQL語言,sql是搜索數據,RE是搜索字符串。正則表達式和SQL語言是開發界的兩個偉大發明。

正則表達式可以用於:

驗證用戶的輸入。

搜索給定數據中的文本。(可在文本編輯器中使用)

編譯器中的解析器

語法突顯,數據包嗅探器等。

要全面了解Regex,我們要理解基本知識,下面我們分別介紹,示例中我們用到在線正則解析網站regex101。

基本量詞(*+?和{n})

正則表示式子中(各語言通用)中的數量詞由*,+.? 和{n}組成。

* 表示匹配零個或多個其先前模式的實例。例如,abc*表示文本必須與'ab'相匹配,後跟零個或多個'c',即文本可能沒有附加'c'並且文本也可能有一個或多個'c'。

+ 匹配其先前模式的一個或多個實例,例如abc+表示文本必須帶有「ab」,後跟一個或多個「c」。所以abc是您可以擁有的至少是正確的,而abcc也是正確的。

?匹配零個或一個出現的模式,例如abc?表示文本可以是abc或ab。

{n}表示與表達式中指定的確切數字(n)匹配。例如a{2}bc表示只能有兩個「a」,然後是一個「bc」和一個「c」。

{n,}至少匹配指定的數字。必須具有n個或更多個前面的表達式,例如ab{2,}c表示必須具有個a,然後是兩個或多個'b',然後是c。

{n,m}表示在模式的n和m(含)之間匹配。這意味著您可以在前至後之間出現m到m個事件。例如ab{2,5}c表示abbc,abbbc,abbbbc,abbbbbc都是正確的。

'.' 匹配所有非空格字符

運算符(|| [] ^和())

|表示「或」。表示與左側的表達式或右側的表達式匹配。例如abc|abd表示文本應為abc或abd。

[]表示文本應與尖括號中的任何字符匹配,例如a[bc]表示文本應為「a」,後跟「b」或「c」。

[0-9]%表示文本應為0到9之間的任何數字,後跟'%'

[a-zA-Z]表示匹配任何一個英文字母,只要介於az或AZ之間即可。

[abc]表示文本或字符串應為a或b或c。

在任何表達式中添加「^」會否定該表達式的含義,例如[^abc]表示匹配任何除abc外的任何字符。

()表示分組,分組後可以在後續反向引用。反向引用存儲與組匹配的字符串部分。可以使用符號$來引用特定的組。$1,$2…代表第一組1,第2組等。默認組為$0,表示字符串本身。例如,我們要刪除行中的所有空格。此示例的正則表達式為以下代碼片段:

private static String backReference(String text) {

String pattern = "(\\w+)([\\s])";

return text.replaceAll(pattern, "$1");

}

上面代碼中的正則表達式有2組:(\\w+)和([\\s])。表示字串是一系列單詞字符(\w+)後跟空格(\s+)。後面一句,我們用組1($1)來替換整個文本,這樣就刪除了空格。

注意:在Java中,我們需要用一個斜槓對字符類(\w和\s)進行轉義,否則會出現語法錯誤。

環視

環視一種排除模式的方法。因此,可以說只有在特定字符串之前沒有改符號時字符串才是有效的,反之亦然。例如,abc(?= d)只要與'd'相符,就會匹配'abc'。 「d」不會被匹配。這叫正向環視或者順序環視。

環視不是所有語言都支持,不是通用的語法,但是妙用可以解決很多問題,比如我們要解析HTML語法:

例如,對html中的一個連接

<a href=』ijz.me』> chognchong</a >

我們要取其中的連接地址

(?=')(.*(?='))

還有一個表示對順序環視的否定表達式,(?!pattern),表示如果'ab'後面沒有'c',則ab(?c)將匹配ab。

注意還有一個逆序環視,java中不支持,我們不介紹。

貪婪和懶惰

正則表達式中的的量詞默認貪婪的,匹配時候會儘可能多的匹配,這樣才能減少遞歸回溯搜索的次數,因而效率最高。例如,對於正則表達式a.+c,希望它表示文本應為'a',後跟一個或多個非空格字符。可能的匹配匹配項為「abcccd」,「abcc」或「abbc」,都是可以的,但是由於貪婪的緣故,它將把所有文本(abcccd abcc abbc)作為一個並返回「abcccd abcc abbc」作為一個結果,因為如果您注意到,第一個字符是「a」,然後是任何其他字符中的一個或多個,它現在以與a.+c完全匹配的c結尾。

為了修改默認的,貪婪模式,只需在量詞前面添加問號(?),這樣使量詞就會只要匹配最少匹配的模式。這時,ab.+?c就會單獨匹配各個字串,而不是整個字符串。

對此的更好應用是:假設您只想從<h1> Chongchong </h1>中單獨獲得標籤<h1>和</h1>,則希望它的正則表達式為<.+>但實際上,它將捕獲整個文本(<h1> Hello Chongchong</h1>)並將其作為一個整體處理。 這時候用?就可以解決

加'?'在量詞前面有時被稱為懶惰模式。

簡而言之,貪婪模式表示匹配儘可能長的字符串,而懶惰模式表示匹配儘可能短的字符串。

字符類

字符類是代表一組字符的轉義序列。下面列出了Java中的一些預定義字符:

\d 表示任意數字;

\s表示空格字符(tab 空格等);

\w 任意單詞字符;

\D表示任意非數字;

\S 表示任意非空格字符;

\W表示任意非單詞字符。

Java中使用正則表達式

好,學習了基礎正則知識後,我們來轉入到Java。來學習在Java中正則表達式的使用。在Java世界Java中的字符串類帶有一個內置的布爾方法,該方法稱為matchs,該方法用來對字符串進行正則匹配。

public static void main(String[] args) {

String value = "12345";

System.out.println("The Result is: "+value.matches("\\d{5}"));

}

上面的代碼段將返回「結果為:true」,因為值(12345)恰好匹配5個字符。除5以外的任何其他值都將返回「結果為:false」。

Pattern/Matcher匹配

除了String類的matchs方法之外,java.util.regex包中也有正則表達式所需的類。它們由三類組成:

Pattern:這是正則表達式的編譯表示。要使用此功能,必須首先在模式類中調用靜態方法(編譯),該方法返回一個模式對象。

Matcher:這是解釋模式並針對輸入字符串執行匹配操作的引擎。要獲得一個對象,必須在Pattern對象上調用matcher方法。

PatternSyntaxException:這表示正則表達式模式中的錯誤

可以使用用模式Pattern/Matcher匹配字符串,一個例子是:

String value = "12345";

String regex = "\\d{5}";

Pattern pattern = Pattern.compile(regex);

Matcher matcher = pattern.matcher(value);

System.out.println("The Result is: "+matcher.matches());

獲取匹配的字符

Matcher支持find和方法lookingAt()獲取匹配的字符,一個例子:

Pattern p=Pattern.compile("\\d+");

Matcher m=p.matcher("aaa2223bb");

m.find();//2223

m.start();//3

m.end();//7,這是2223後的索引號

m.group();//2223

也可以使用lookingAt()方法,只之前的字符串:

Mathcer m2=m.matcher("2223bb");

m.lookingAt(); // 2223

m.start(); // 0,由於lookingAt()只能匹配前面的字符串, start()方法總是返回0

m.end(); // 4

m.group(); // 2223

性能問題

這樣需要每次都先創建 Pattern/Matcher對象耗費資源太大,性能不行。使用Pattern/Matcher是在String類中實現了方法匹配。因此,對於匹配的每個字符串,它都會在匹配之前創建一個Pattern對象。為了解決這個問題,我們可以使用預編譯方法,下面是一個實例:

上面的代碼將數組中的所有元素與特定的正則表達式([a-zA-Z]*log[a-zA-Z]*)進行匹配。正則表達式用來獲取所有帶有「log」一詞的文本。在與正則表達式匹配之前,必須先編譯該表達式(Pattern.compile);

第一個方法matchUsingPatternMatcher()在尋找匹配項之前先編譯模式,而第二個方法matchUsingStringMatches()創建一個新的模式對象

數組中每個元素的鏡像(Pattern.compile())操作比較耗費內存,並且當數據/文本過多時,還可能會導致內存洩漏

因此,如果在處理大量數據比較關心性能時,請使用Pattern/Matcher類先進行編譯,然後使用實例來匹配文本。

相關焦點

  • java正則表達式入坑指南
    在日常開發工作中,無論你使用的語言是java、python、shell、golang還是C#, 正則表達式是程式語言中幾乎繞不開的話題。有了它,可以幫你快速定位到符合條件的文本內容。今天小編帶大家一起來學習下正則表達式,相信通過這篇文章的介紹,能為以後的工作提供一個更清晰的思路。
  • Java 正則表達式中分組的3種不同用法,乾貨分享!
    正則表達式中分組說明正則表達式可以通過」()」來進行分組,更專業的表達就是捕獲組,每個完整的」()」可以分為一組,同時,」()」中還可以嵌套」()」,即組之間還可以存在更小的組,以此類推。而編號為0的組,則是正則表達式匹配到的整體,這個規則只要支持正則表達式中捕獲組的語言基本上都適用。捕獲組就是把正則表達式中子表達式匹配的內容,保存到內存中以數字編號或顯式命名的組裡,方便後面引用。當然,這種引用既可以是在正則表達式內部,也可以是在正則表達式外部。
  • JavaScript正則表達式「程式設計師培養之路第十二天」
    第一節 基本概念正則表達式(regular expression)描述了一種字符串匹配的模式,他是一個特殊的公式,由原子、元字符、模式修正符組成;它也是一個字符串!只不過是一個特殊的字符串主要實現對字符串的匹配、分割、查找、替換等操作 正則表達式的主要作用: 正則匹配: 可以測試字符串內容是否可以與正則相匹配 替換文本: 根據模式匹配字符串中的特定內容,進行替換、刪除 提取數據: 根據模式匹配從字符串中提取內容
  • 8分鐘看完,徹底掌握Java正則表達式的十大問題!
    這篇文章總結了有關Java正則表達式的主要問題。希望可以給同學們帶來java學習路上的成長!1.如何從字符串中提取數字?使用正則表達式的一個常見問題是將所有數字提取到整數數組中。4.如何轉義文本以進行正則表達式?通常,正則表達式使用「 \」轉義結構,但是要在反斜槓之前加上另一個反斜槓以使Java字符串得以編譯是很痛苦的。用戶還有另一種方式將字符串Literals傳遞給Pattern,例如「 $ 5」。
  • 正則表達式斷言精講Java語法實現
    斷言本文目的是講解正則表達式之斷言用法。目前網際網路上有很多博文對斷言講解的並不透徹,如果您剛開始學習斷言,相信此博文會對您有幫助。1.2.3.1 情景導入假設,我要獲得一個字符串裡面所有以空格開頭的英文詞語。
  • Python中的正則表達式
    什麼是正則表達式正則表達式是用於處理字符串的強大工具,它使用預定義的特定模式去匹配一類具有共同特徵的字符串,主要用於快速、準確地完成複雜字符串的查找、替換等。正則表達式進行匹配的流程如下圖所示:正則表達式匹配過程是:依次拿出表達式和文本中的字符比較,如果每一個字符都能匹配,則匹配成功;一旦有匹配不成功的字符則匹配失敗。
  • Java 正則表達式用法總結二
    字符串:(空串) find返回true表達式:(foo)+ 字符串:foo find返回true表達式:(foo)* 字符串:(空串) find返回true表達式:a{3,} 字符串:bbaaaaccc find返回true,group是aaaa表達式:a{3,4} 字符串:bbaaaaaccc find返回true,group是aaaa;因為匹配次數需要滿足至少
  • Python 正則表達式-函數用法分析
    Python正則表達式的主要作用是檢索、替換符合匹配規則的文本,什麼時候檢索,什麼時候替換,我們根據需求,選擇最合適的函數。【函數一】compile(pattern, flags=0)我們編寫的正則表達式 pattern,指定使用的模式 flags 默認為0 即不使用任何模式【函數二】 purge()這個函數的作用是清除緩存中的正則表達式【函數三】escape(pattern)如果需要操作的文本中含有正則的元字符時,需要將元字符加上反斜扛
  • 正則表達式:如何匹配一個或多個字符?
    Ben是一個正則表達式。因為本身是純文本,所以看起來可能不像是一個正則表達式,但它的確是。正則表達式可以包含純文本(甚至可以只包含純文本)。當然,像這樣使用正則表達式是一種浪費,但把它作為我們學習正則表達式的起點還是很不錯的。我們來看一個例子:這裡使用的正則表達式是純文本,它將匹配原始文本裡的Ben。
  • 超好用的6種正則表達式,前端開發人員必知!
    來源:Pexels正則表達式已經成為程式設計師的必備工具。幾乎所有流行的程式語言都支持正則表達式,原因如下:正則表達式為開發人員提供了強有力的工具,使之能快速執行需要幾十行代碼才能完成的任務。本文主要研究前端開發人員經常要面對的六大文本處理和操作任務,並進一步了解正則表達式如何簡化這一過程。但也只是觸及了正則表達式潛力之皮毛。1.
  • python正則表達式使用方法說明
    曾光紅/文 (同步發布豆瓜網)一、導入re庫python使用正則表達式要導入re庫。import re在re庫中。正則表達式通常被用來檢索查找、替換那些符合某個模式(規則)的文本。二、使用正則表達式步驟1、尋找規律;2、使用正則符號表示規律;3、提取信息,如果每一個字符都能匹配,則匹配成功;一旦有匹配不成功的字符則匹配失敗。
  • Python正則表達式:特殊符號和字符
    正表達式為高級的文本模式匹配,抽取,與/或文本形式的搜索和替換功能提供了基礎。簡而言之,正則表達式(簡稱regex)是由一些字符和特殊符號組成的字符串,它描述了模式的重複或者表達多個字符。python通過標準庫中的re模塊來支持正則表達式。
  • 原創通俗易懂的Python的正則表達式,建議收藏
    正則表達式正則表達式是一個特殊的字符序列,由普通字符和元字符組成。元字符能幫助你方便的檢查一個字符串是否與某種模式匹配。正則表達式應用的場景也非常多。常見的比如:搜尋引擎的搜索、爬蟲結果的匹配、文本數據的提取等等都會用到,所以掌握甚至精通正則表達式是一個硬性技能,非常必要。
  • Shell—正則表達式(grep命令、sed工具)
    前言正則表達式對於系統管理員來說是非常重要的,熟練運用正則表達式可使工作變得更加簡單、方便。一、正則表達式概述正則表達式定義正則表達式,又稱正規表達式、常規表達式使用字符串來描述、匹配一系列符合某個規則的字符串簡單來說,是一種匹配字符串的方法,通過一些特殊符號,實現快速查找、刪除、替換某個特定字符串。
  • JavaScript-正則表達式中的修飾符和對象有哪些?
    本節主要內容:1.什麼是正則表達式2.正則表達式進階3.正則表達式高級學習目標:一、正則表達式正則表達式概念:正則表達式(英文為regular Expression)是一種【字符串檢索模式】正則表達式具體表現為一個字符串的樣子。
  • Linux系統正則表達式用法筆記
    正則表達式:能用某種模式去匹配一類字符串的公式,它是由一串字符和元字符組成的字符串。元字符就是闡述字符表達式的內容、轉換和描述各種操作信息的字符。常見的一些基礎的正則表達式1、「.」圓點符號用來匹配除換行符之外的任意一個字符。
  • Python學習第137課——正則表達式中實現可選規則
    正則表達式英文是Regular Expression,各種程式語言中都是把它簡寫成Regex,或者Regexp或者re。這節我們學習如何在正則表達式中實現可選規則。●用小括號和pipe(豎線|)實現每一個可選項例1:現在假設我們有一個應答機器人,接到了很多很多用戶的留言,這些留言中包括用戶自己的姓名、聯繫電話等信息。
  • Java中Lambda表達式的5種不同語法
    主體,由單個表達式或語句塊組成。在這種情況下,它是一個單一表達式-Integer.compare(m.length(), n.length())Output:[a, is, java, site, creek, program]2.可以推斷參數類型
  • Python中使用re模塊實現正則表達式的分割字符串操作
    第八十四節:正則表達式實現分割字符串操作分割字符串的方法在前面就學習過,用正則表達式實現分割字符串,使用的依然是split()方法,分割後也是返回一個列表,不同點在哪裡呢?先回憶一下直接使用split()方法分割字符串的語法格式Python中如何分割、合併字符串:str.split(sep,maxsplit)再來看使用正則表達式正則表達式的基礎知識和Python中的基本應用來分割字符串的語法格式:re.split(pattern,str,maxsplit,flags)兩相比較,就可以直觀的發現相同點和不同點了
  • 怎樣用正則表達式判斷輸入框中是否是車牌號
    【判斷輸入是否是五個字母和數字】第二步就是我們用正則方法判斷輸入的內容具體是什麼,我們var re = new RegExp('^[A-Za-z0-9]{5}$');這樣寫是判斷輸入的內容是五個字母加數字