正則表達式斷言精講Java語法實現

2020-12-16 計算機java編程

斷言

本文目的是講解正則表達式之斷言用法。目前網際網路上有很多博文對斷言講解的並不透徹,如果您剛開始學習斷言,相信此博文會對您有幫助。

1.2.3.1 情景導入

假設,我要獲得一個字符串裡面所有以空格開頭的英文詞語。

在使用上面的代碼過程中存在一些問題,我獲得的單詞默認是前頭帶空格的,縱然我可以通過String類的trim來解決這些問題,可是這樣用起來會很麻煩,有沒有一種正則表達式的規則可以檢測那些開頭帶空格的詞彙但是適配到的詞彙不帶空格呢?答案是有的,那就是斷言

什麼是斷言

在使用正則表達式時,有時我們需要捕獲的內容前後必須是特定內容,但又不捕獲這些特定內容的時候,零寬斷言就起到作用了。

斷言全稱為零寬斷言

斷言的語法規則

零寬斷言為什麼叫零寬斷言

理解這一點至關重要,拿零寬前行正向斷言來舉例

零寬

零寬的含義為斷言部分不佔據寬度,舉個例子12(?=la)匹配12la匹配到的是12,含義是la前面的12。

12la匹配12la匹配到的是12la,含義為匹配value為12la的字符串。不知道通過這個例子你能否看懂零寬的意義,不懂也沒關係,看完接下來幾章就會懂了。

前行

前行的含義我可以確定我說的是正確的,現在網際網路上好多人對前行的理解是錯誤的,雖然按照他們的解釋是可以解釋的通大多數情況,但是我們還是要抱著實事求是的態度,還原前行真正的含義,參考網站:正則表達式零寬斷言詳解(?=,?<=,?!,?,Regular expression to match a line that doesn't contain a word。

在正則表達式中,每個字符串都是有定位的,所謂定位,就是確定字符串中每個字符位置的數字,這個只可意會,我給您看幾張圖,通過圖片,或許可以理解

看到沒有,字符串每一個字符間隔就是一個個位置點,字符串第一個字符前為位置0,字符串第一個字符和第二個字符之間為位置1,字符串第一個字符位於位置0和位置1之間,以此類推……

前行的意義為位置之前,後行的意義為位置之後

如上圖,位置5位於紅色區域後行,位置5位於黃色區域前行

那麼,在斷言中前行和後行代表著什麼呢?

比如說正則表達式12(?=la)在匹配字符串qwew12bb12la的時候,他會先,匹配到從左往右第一個12,如下圖所示

因為(?=x)是前行匹配,這個時候12是佔位置的,位置點走到了第一個12的後面,即位置6,。因為是零寬,(?=la)不佔位置,接下來以位置6為前行,匹配位置6的後面,位置6的後面不是la,故不匹配位置6前面的12,接下來位置轉到了第二個12後面,如下圖所示

因為是前行匹配,位置10作為前行,匹配後面的字符,後面是la符合要求,因為零寬,匹配到的最終字符不包括零寬,如下圖所示

不懂也沒關係,看完接下來幾章就會懂了。

負向

所謂負向,不符合為負向,如(?<!x)

就是負向,該斷言匹配的是不符合x標準的字符串作為目標字符串的後行

再來熟悉一下幾個斷言

斷言DEMO

後行正向斷言,該斷言匹配前面是aa的字符

運行結果為

dfdsfs

後行負向斷言,該斷言匹配的是前面不是$的數字

運行結果為

matcher1.group() = 23

我來解釋一下,正則表達式(?<!\\$|\\d)\\d+,斷言的意思是不匹配前面為$或數字的數字。

模擬一下匹配的過程,也許會更加明白是怎麼一回事兒,先說一下"$14 23",位置我就不在圖中標了,自己數一下吧

(?<!\\$|\\d)\\d+先匹配數字,匹配到了1,位置是1,因為斷言是不佔寬度的。因為是後行,檢測到左邊是,符合要求,故匹配23

先行正向斷言

運行結果是

matcher2.group() = windows

我來稍微解釋一下,"(?i)windows(?=2000|xp|10)"(?i)表明不區分大小寫,Windows表明適配windows,(?=2000|xp|10)表明是零寬先行正向斷言。我說一下匹配的過程,首先匹配windows,位置來到了windows後,零寬先行,後面是xp適配成功。

先行負向斷言

運行結果是

matcher3.group() = linux

這個就不解釋了,自行理解吧

以上四個demo是最最基礎的demo,在很多教程上對斷言的講解止步於此(實際上,很短教程連最基本的匹配過程都沒講,只講了匹配的結果,這個要出大問題的),務須掌握好上面的四個demo。

斷言的基礎應用和實際用處

放一張思維導圖

這個我先說一下結論,在實際應用開發中,在應用諸如驗證開頭或結尾(只要求一行的開頭或結尾)的實踐中,大概有兩種,一種是零寬,一種是非零寬。所謂零寬即匹配的數據不包括斷言,非零寬反之,在某些情況下需要藉助String方法的subString()方法。

一般情況下,使用斷言,主要是用它零寬的屬性,驗證開頭包含,結尾包含時一般不用斷言,分組就能解決問題,當開頭不包含或結尾不包含等問題時,使用斷言是很好的辦法。

演示三個

驗證不包含

運行結果如下

驗證不包含 matcherError.group() = wqeqr12eqr34512 !"wqer12335".contains("123") = false

解析:正則表達式裡字符串"不包含"匹配技巧 | 外刊IT評論

驗證開頭包含

一行字符串,驗證開頭是否包含某字符串,若包含則輸出匹配到的數據,此方法會包括斷言。也就是說假如驗證「123erre」的開頭是否是123,匹配到的數據為123erre而不是erre。驗證開頭包含且匹配數據不包括斷言請看下一章

結果如下

驗證開頭包含 falsematcherRight.group() = wercdv

解析:

^(?=wer).*匹配wercdv的時候,先因為^來到了位置0,位置0後面是符合.*的,遂開始匹配斷言,注意這時候位置依然在位置0,因為是先行斷言,位置0後面是wer符合斷言要求,故匹配到了wercdv

驗證開頭包含且匹配到的數據不包括斷言

假如說要匹配開頭是wer的字符串,字符串是wercdv,匹配到的是cdv而不是wercdv

結果如下

驗證開頭包含,匹配到的數據不包括斷言false matcherRight.start() = 0matcherRight.end() = 6matcherRight.group() = cdv

解析:

^wer(?<=wer)(.*)因為^所以先來到了位置0,然後匹配wer,來到了位置3,位置3後面符合.*的要求,因為後行匹配,前面是wer,符合要求,在取出的過程中,有一個分組,選取的是.*故最終取出cdv

驗證結尾包含,且匹配到的數據不包括斷言

舉個例子,匹配以「元」結尾的詞彙,且匹配到的數據不包括「元」,譬如「12元」,匹配到的數據是12。

運行結果是

驗證結尾包含,且獲得結尾之前的數字matcherRight.group(1) = 12

解析:

(\\d+)(?=元).$因為$先來到位置3,如圖所示

然後因為(\\d+)(?=元).$的.,位置向前一步,來到了位置2,然後前行斷言,位置2的後面是元,前面是數字符合要求,如下圖所示

匹配到了「12元」,因為輸出組①,故最終輸出12。

斷言基礎應用總體代碼

代碼文件,運行結果寫在了注釋裡面

不按套路出牌,幫你徹底理解斷言

一般情況下,使用斷言,主要是用它零寬的屬性,向驗證開頭包含,結尾包含時一般不用斷言,分組就能解決問題,當開頭不包含或結尾不包含等問題時,使用斷言是很好的辦法。

絕大多數網站在講解斷言問題的時候總是去引用斷言demo一章裡面那四個例子,這會給人造成一種「前行斷言適配結尾,後行斷言適配開頭」的錯覺,事實上並不是這個樣子,重要的是要具體問題具體分析。如同上面的代碼,不按所謂常理出牌,有助於正則表達式之理解。

上面取了四個例子,皆不按套路來,為方便理解,選一個細講

運行結果

不按套路來的零寬後行負向斷言 matcher3.group() = lla

(?i)\\w+(?<!re)a的本意是不區分大小寫地去適配結尾是a且a的前面不是re的字符。(?!)是不區分大小寫的意思。正則發揮作用時,先找到a,位置來到a的前面,因為後行斷言,位置的前面不能是re。因為\\w+,a的前面需要是字母或數字。綜合看來,意思是a的前面是除re之外的字母或數字。

如果真的不理解,就死記下面的實例

不包含a

開頭不包含a

結尾不包含a

包含a且不包含b

處於a和b之間

適配字符串中所有不以b結尾的數字

適配字符串中所有以a開頭的數字

在某些時候亦可以用\b來實現某些可以用斷言實現的正則表達,舉個例子

獲取所有以b結尾的數字

查看代碼:

相關焦點

  • Java的正則表達式和捕獲組
    正則表達式定義了字符串的模式。正則表達式可以用來搜索、編輯或處理文本。正則表達式並不僅限於某一種語言,在Java、JavaScript等語言都存在,但是在每種語言中有細微的差別。Java正則表達式正則表達式實例一個字符串其實就是一個簡單的正則表達式,例如 Hello World正則表達式匹配 "Hello World" 字符串。.
  • 給JAVA程式設計師的正則表達式一課
    正則表達式可以用於:驗證用戶的輸入。搜索給定數據中的文本。(可在文本編輯器中使用)編譯器中的解析器語法突顯,數據包嗅探器等。要全面了解Regex,我們要理解基本知識,下面我們分別介紹,示例中我們用到在線正則解析網站regex101。基本量詞(*+?
  • 正則表達式在VBA中間是如何應用?正則表達式的實現方式?
    Hi,大家好,本章節開始將會從零開始和大家用圖文的方式,讓你從零基礎學會正則表達式!有興趣的小夥伴可以持續關注我,或者在專欄中進行查看自我學習,願與君攜手前行!在上一個章節說到正則表達式的入門級知識點,本節將會與大家分享一下正則表達式的是具體實現方式是怎麼樣的?
  • java正則表達式入坑指南
    在日常開發工作中,無論你使用的語言是java、python、shell、golang還是C#, 正則表達式是程式語言中幾乎繞不開的話題。有了它,可以幫你快速定位到符合條件的文本內容。今天小編帶大家一起來學習下正則表達式,相信通過這篇文章的介紹,能為以後的工作提供一個更清晰的思路。
  • P18 Python正則表達式貪婪、向後引用、零款斷言
    title: P18|Python正則表達式中的貪婪、向後引用、零寬斷言author: Adolph Leecategories: 編程基礎tags:Python基礎正則表達式斷言在計算機編程中,正則表達式堪稱我們處理字符串的神奇
  • 程式設計師入門基礎:python正則表達式的零寬斷言
    一、零寬斷言此篇文章為python正則表達式的高階入門,正則基礎入門請參考程式設計師入門基礎:python的正則表達式。斷言也可以理解為判斷的意思,正則表達式中有很多這樣的斷言,常見的如 ^ 和 /A,匹配字符串或者行的末尾 $ 和 /Z,單詞邊界/B等等。
  • 德州點創教育JavaScript正則表達式授課大綱
    ;); 匹配a、b、c中的任意一個字符第二種:通過直接量語法創建,直接量的定義包含在一對斜槓(/)之間,這種方式更常用。,許多標點符號都有特殊的含義,如果想到正則表達式中使用這些字符的直接量進行匹配,則必須使用前綴\特殊含義字符: ^ $ . * + = !
  • Python正則表達式急速入門
    正則表達式在程序開發中會經常用到,比如數據(格式)驗證、替換字符內容以及提取字符串內容等等情況都會用到,但是目前許多開發人員對於正則表達式只是處於了解或者是基本會用的階段。一旦遇到大批量使用正則表達式的情況(例如網絡爬蟲)可以說基本上就抓瞎了。這篇文章我將帶領大家利用 Python 來學習一下正則表達式。
  • 一篇文章搞定Python正則表達式
    正則表達式語法1.1 字符與字符類1 特殊字符:.^$?來實現1.3 組與捕獲1 ()的作用:1. 捕獲()中正則表達式的內容以備進一步利用處理,可以通過在左括號後面跟隨?1.4 斷言與標記斷言不會匹配任何文本,只是對斷言所在的文本施加某些約束1 常用斷言:1.
  • 新的JavaScript功能將改變編寫正則表達式的方式
    大多數程式語言都支持正則表達式,使用正則表達式最好的理由:它們是用於處理文本的極其強大的工具,需要幾十行代碼的文本處理任務通常可以通過一行正則表達式代碼來完成。雖然大多數語言中的內置函數通常足以對字符串執行搜索和替換操作,但更複雜的操作(例如驗證文本輸入)通常需要使用正則表達式。
  • 「JAVA」從格式化輸出到掃描輸入,深究Java正則表達式匹配之道
    正則表達式中的字符序列在Java 中的CharSequence類是用來表示字符序列的,在字符序列中定義了一些用於操作字符序列的api,而Java 中大部分與字符串相關的類都實現了CharSequence接口,所以正則表達式操作都能接受CharSequence類型的參數。
  • 8分鐘看完,徹底掌握Java正則表達式的十大問題!
    這篇文章總結了有關Java正則表達式的主要問題。希望可以給同學們帶來java學習路上的成長!1.如何從字符串中提取數字?使用正則表達式的一個常見問題是將所有數字提取到整數數組中。在Java中,\d表示數字範圍(0-9)。儘可能使用預定義的類將使您的代碼更易於閱讀,並消除了格式錯誤的字符類所引起的錯誤。
  • 30 分鐘輕鬆搞定正則表達式基礎
    正則表達式簡介提起正則表達式,可能大家的第一印象是:既強大好用但也晦澀難懂。正則表達式在文本處理中相當重要,各大程式語言中均有支持(跟 Linux 三劍客結合更是神兵利器)。但是針對字符串』W12345678『,只有第二個可以正確匹配出』12345678『,原因在於第一個正則表達式的意思匹配一個字符串只有6-10個數字組成,而第二個正則表達式意思是匹配字符串中的6-10個連續數字。除了這三個元字符表示位置外,還有零寬斷言、負向零寬斷言也表示位置,後續會詳細介紹。
  • Java - 斷言(assert)使用和陷阱
    二、語法在Java中,assert關鍵字是從JAVA SE 1.4 引入的,為了避免和老版本的Java代碼中使用了assert關鍵字導致錯誤,Java在執行的時候默認是不啟動斷言檢查的(這個時候,所有的斷言語句都 將忽略!)
  • Java 正則表達式中分組的3種不同用法,乾貨分享!
    正則表達式中分組說明正則表達式可以通過」()」來進行分組,更專業的表達就是捕獲組,每個完整的」()」可以分為一組,同時,」()」中還可以嵌套」()」,即組之間還可以存在更小的組,以此類推。而編號為0的組,則是正則表達式匹配到的整體,這個規則只要支持正則表達式中捕獲組的語言基本上都適用。
  • PHP正則表達式核心技術完全詳解 第1節
    (一) php正則表達式的介紹:正則表達式: 就是描述字符串排列模式的一種自定義語法規則、也是用於描述字符串排列 或 匹配模式的一種語法規則、正則表達式: 就是用於描述字符串排列 或 匹配模式的一種語法規則、它主要用於字符串的: 分割字符串、查找字符串、替換字符串 的一系列操作在php中 正則表達式一般是由一些特殊字符聯合構成的一個文本模式描述
  • JavaScript正則表達式常用技巧
    正則表達式的掌握程度能粗略地看出程式設計師的技術底子,所以技術面試、編程競賽等 都特別喜歡考察正則表達式。本篇就帶你一起夯實一下 JavaScript 正則表達式的一些使用技巧:創建正則表達式在 JavaScript 的世界,創建正則表達式有2個方法: (1)使用一個正則表達式字面量,其由包含在斜槓之間的模式組成。
  • 正則表達式(三)
    四、貪婪模式與非貪婪模式1.貪婪模式:正則表達式匹配時,會儘量多的匹配符合條件的內容舉例如下:注意:grep默認採用貪婪匹配,可能會對我們的測試結果造成幹擾,大家可以上網使用「正則在線轉換工具」進行測試2.非貪婪模式:正則表達式匹配時,會儘量少的匹配符合條件的內容,
  • 從0到1打造正則表達式執行引擎
    理解原理可以讓你以後寫字符串匹配時正則表達式能夠信手拈來,理解原理也是觸類旁通的基礎。廢話不多說,直接開始正式內容。本文是我個人做的動手實踐性項目,所以未完整支持所有語法,而且因為是用NFA實現的所以性能比生產級的執行引擎差好多。目前源碼已開放至https://github.com/xindoo/regex,後續會繼續更新,歡迎Star、Fork 提PR。
  • 看完你就會正則表達式了
    最近看了一篇關於正則表達式的學習筆記,覺得講的非常好,更有圖形化的神器相助,想不學會都難,所以想轉給大家看看。話說不是開發為啥要學正則表達式這種看似很晦澀的東西呢,因為現在很多搜索的場景都是支持正則表達式的,學會了正則表達式就有如一把利劍在手。本文較長,建議抽40分鐘完整的時間一次讀完再慢慢消化。