詳細講解平衡組_正規表示式
這篇文章主要介紹了正規表示式——詳細講解平衡組,需要的朋友可以參考下
##這篇文章適合你嗎?
要讀懂這篇文章的精髓,你最好要有一點正規匹配原理的基礎。例如".*?"匹配文字內容"asp163",稍懂正規表示式的人都知道可以匹配,但是你知道他的匹配過程嗎?如果你不太清楚,那麼下面的內容,對你來說可能不太適合,或許,看的太吃力且無法領悟平衡組的用法。因此,我建議你先了解正規表示式NFA引擎的匹配原理。想要整理一份易懂易描述的話,的確要花些時間,但我不知道這篇內容會不會達到我預期的效果。慢慢完善吧~(註:這是我2010年寫的,現在拿過來,有時間將自己做為讀者來看本篇文章,修改有問題的地方,並增加些實例,盡量做到通俗易懂。舉個例子吧,如何把“xx字符串
#裡,最長的尖括號內的內容捕獲出來?這裡需要用到以下的語法建構:
(?把捕獲的內容命名為group,並壓入堆疊( ?<-group>)
從堆疊上彈出最後壓入堆疊的名為group的捕獲內容,如果堆疊本來為空,則本分組的匹配失敗
(?(group)yes |no) 如果堆疊上存在以名為group的捕獲內容的話,繼續匹配yes部分的表達式,否則繼續匹配no部分
(?!) 順序否定環視,由於沒有後綴表達式,試圖匹配總是失敗
如果你不是一個程式設計師(或者你是一個對堆疊的概念不熟的程式設計師),你就這樣理解上面的三種語法吧:第一個就是在黑板上寫一個(或再寫一個)"group",第二個就是從黑板上擦掉一個"group",第三個就是看黑板上寫的還有沒有"group",如果有就繼續配對yes部分,否則就符合no部分。 我們需要做的是每碰到了左括號,就在黑板上寫一個"group",每碰到一個右括號,就擦掉一個,到了最後就看看黑板上還有沒有——如果有那就證明左括號比右括號多,那匹配就應該失敗(為了能看得更清楚一點,我用了(?'group')的語法):
< #最外层的左括号 [^<>]* #最外层的左括号后面的不是括号的内容 ( ( (?'Open'<) #碰到了左括号,在黑板上写一个"Open" [^<>>]* #匹配左括号后面的不是括号的内容 )+ ( (?'-Open'>) #碰到了右括号,擦掉一个"Open" [^<>]* #匹配右括号后面不是括号的内容 )+ )* (?(Open)(?!)) #在遇到最外层的右括号前面,判断黑板上还有没有没擦掉的"Open";如果有,则匹配失败 > #最外层的右括号
我為什麼寫這篇文章
看了上面的介紹,你懂了嗎?在我未理解正規表示式匹配原理之前,請先看上面對於平衡組的介紹,似懂非懂,且只能當做模板記住,而不能靈活運用。因此查閱大量有關正規方面的資料,這裡尤其感謝lxcnn的技術文檔及《精通正則表達式》這本書,讓我對正則表達式有了更深入、更系統的理解,因此,在它們的基礎之上,我就結合自己的學習經驗做個小結,一來做為學習筆記存檔,另外,如果能解決你的疑惑,也是件讓人高興的事。
我先暫不分析上面的程式碼,先來講解一下關於平衡組相關的概念及知識。
平衡組的概念及作用
平衡組,故名思義,平衡即對稱,主要是結合幾種正則語法規則,提供對配對出現的嵌套結構的匹配。平衡組有狹義與廣義兩種定義,狹義平衡組指
(?Expression)
平衡組的匹配原理平衡組的匹配原理可以用堆疊來解釋,先舉個例子,再根據例子來解釋。
來源字串:a+(b*(c+d))/e+f-(g/(h-i))*j正規表示式:
( (?
輸出:(b*(c+d)) 和(g/(h-i))<br/>
我將上面正規表示式程式碼分行寫,並加上註釋,這樣看起來有層次,而且方便<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'> \( #普通字符“(”
( #分组构造,用来限定量词“*”修饰范围
(?<Open>\() #命名捕获组,遇到开括弧“Open”计数加1
| #分支结构
(?<-Open>\)) #狭义平衡组,遇到闭括弧“Open”计数减1
| #分支结构
[^()]+ #非括弧的其它任意字符
)* #以上子串出现0次或任意多次
(?(Open)(?!)) #判断是否还有“Open”,有则说明不配对,什么都不匹配
\) #普通闭括弧</pre><div class="contentsignin">登入後複製</div></div>
對於一個嵌套結構而言,開始和結束標記都是確定的,對於本例開始為“(”,結束為“)”,那麼接下來就是考察中間的結構,中間的字符可以劃分為三類,一類是“(”,一類是“)”,其餘的就是除這兩個字符以外的任意字符。
那麼平衡組的匹配原理就是這樣的<p>1、先找到第一个“(”,作为匹配的开始。即上面的第1行,匹配了:a+(b*(c+d))/e+f-(g/(h-i))*j (红色显示部分)</p><p>2、在第1步以后,每匹配到一个“(”,就入栈一个Open捕获组,计数加1</p><p>3、在第1步以后,每匹配到一个“)”,就出栈最近入栈的Open捕获组,计数减1</p><p>也就是讲,上面的第一行正则“\(”匹配了:<code>a+(b*(c+d))/e+f-(g/(h-i))*j
(红色显示部分)
然后,匹配到c前面的“(”,此时,计数加1;继续匹配,匹配到d后面的“)”,计算减1;——注意喽:此时堆栈中的计数是0,正则还是会向前继续匹配的,但是,如果匹配到“)”的话,比如,这个例子中d))(红色显示的括号)——引擎此时将控制权交给(?(Open)(?!))
,判断堆栈中是否为0,如果为0,则执行匹配“no”分支,由于这个条件判断结构中没有“no”分支,所以什么都不做,把控制权交给接下来的“\)”
这个正则表达式“\)”可匹配接下来的),即b))(红色显示的括号)
4、后面的 (?(Open)(?!))
用来保证堆栈中Open捕获组计数是否为0,也就是“(”和“)”是配对出现的
5、最后的“)”,作为匹配的结束
匹配过程
首先匹配第一个“(”,然后一直匹配,直到出现以下两种情况之一时,把控制权交给(?(Open)(?!)):
a)堆栈中Open计数已为0,此时再遇到“)”
b)匹配到字符串结束符
这时控制权交给(?(Open)(?!))
,判断Open是否有匹配,由于此时计数为0,没有匹配,那么就匹配“no”分支,由于这个条件判断结构中没有“no”分支,所以什么都不做,把控制权交给接下来的“\)”
如果上面遇到的是情况a),那么此时“\)”可以匹配接下来的“)”,匹配成功;
如果上面遇到的是情况b),那么此时会进行回溯,直到“\)”匹配成功为止,否则报告整个表达式匹配失败。
由于.NET中的狭义平衡组“(?<Close-Open>Expression)
”结构,可以动态的对堆栈中捕获组进行计数,匹配到一个开始标记,入栈,计数加1,匹配到一个结束标记,出栈,计数减1,最后再判断堆栈中是否还有Open,有则说明开始和结束标记不配对出现,不匹配,进行回溯或报告匹配失败;如果没有,则说明开始和结束标记配对出现,继续进行后面子表达式的匹配。
需要对“(?!)
”进行一下说明,它属于顺序否定环视,完整的语法是“(?!Expression)
”。由于这里的“Expression”不存在,表示这里不是一个位置,所以试图尝试匹配总是失败的,作用就是在Open不配对出现时,报告匹配失败。
下面在看个例子:
<table> <tr> <td id="td1"> </td> <td id="td2"> <table> <tr> <td>snhame</td> <td>f</td> </tr> </table> </td> <td></td> </tr> </table>
以上为部分的HTML代码.现在我们的问题是要提取出其
<td id="td2"> <table> <tr> <td>snhame</td>
原因也很简单,它和离他最近的标签匹配上了,不过它不知道这个标签不是它的-_-,是不是就是?符号的原因呢,我们去掉让他无限制贪婪,可这下问题更大了,什么乱七八糟的东东它都匹配到了
<td id="td2"> <table> <tr> <td>snhame</td>f
这个结果也不是我们想要的。那么我就用“平衡组”来解决吧。
匹配的结果是
<td id="td2"> <table> <tr> <td>snhame</td>f
这正是我们想要的
注意,我开始写成这样的方式
<td\s*id="td2"[^>]*>((?<mm><td[^>]*>)+|(?<-mm></td>)|[\s\S])*(?(mm)(?!))</td>
匹配的结果是
<td id="td2"> <table> <tr> <td>snhame</td>f
一个问题
以下代码只是做为一个问题探讨
文本内容:e+f(-(g/(h-i))*j
正则表达式:
\( ( (?<mm>\() | (?<-mm>\)) | . )*? (?(mm)(?!)) \)
匹配的结果是:(-(g/(h-i))
以上是詳細講解平衡組_正規表示式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Golang正規表示式使用管道符|來匹配多個單字或字串,將各個選項作為邏輯OR表達式分隔開來。例如:匹配"fox"或"dog":fox|dog匹配"quick"、"brown"或"lazy":(quick|brown|lazy)匹配"Go"、"Python"或"Java":Go|Python |Java匹配字或4位郵遞區號:([a-zA

PHP正規表示式是一種針對文字處理和轉換的強大工具。它可以透過解析文字內容,並依照特定的模式進行替換或截取,達到有效管理文字資訊的目的。其中,正規表示式的一個常見應用是替換以特定字元開頭的字串,對此,我們進行如下的講解

php用正規去除中文的方法:1、建立一個php範例檔;2、定義一個含有中文和英文的字串;3、透過「preg_replace('/([\x80-\xff]*)/i', '',$a);」正規方法去除查詢結果中的中文字元即可。

在本文中,我們將學習如何使用PHP正規表示式刪除HTML標籤,並從HTML字串中提取純文字內容。為了示範如何去除HTML標記,讓我們先定義一個包含HTML標籤的字串。

為了PC的順利運行,系統的所有功能和服務都應該可以正常運作。從圖片或視訊質量,到導航或音響系統。任何這些都出現問題,您開始面臨圖形、視訊、聲音等問題。無論您是否是普通用戶,您都需要聲音服務每天都能正常運作。但是,有時,您可能會在聲音服務中遇到不同的問題,其中之一是左聲音或右聲音無法正常工作。這可能很煩人,尤其是當您正在觀看影片、參加或主持線上會議、聽音樂等時。此問題主要是由於系統左右聲音之間的不平衡所造成的。因此,我們在這裡列出了一個修復程序,可以幫助您平衡Windows11PC上的左/右聲音。

網站安全性越來越受到關注,使用HTTPS協議保證資料傳輸的安全性已成為目前網站開發的重要內容。在PHP開發中,如何使用正規表示式驗證URL是否為HTTPS協定呢?下面我們就來了解一下。正規表示式正規表示式是一種用來描述規律的表達式,是處理文字的強大工具,被廣泛應用於文字匹配、搜尋和替換等方面。在PHP開發中,我們可以透過正規表示式來匹配URL中的http

PHP正規替換實例:快速掌握替換技巧隨著網路的發展,網站開發變得越來越常見。在網站開發中,經常需要對字串進行替換操作,而正規表示式是一種非常強大的工具,能夠在字串中快速進行搜尋和替換操作。本文將介紹如何利用PHP語言中的正規表示式進行替換操作,並提供具體的程式碼範例,幫助讀者快速掌握替換技巧。 1.preg_replace函數在PHP中,可以使用preg

使用PHP正規實現中文替換功能的技巧分享在web開發中,經常會遇到需要對中文內容進行替換的情況。 PHP作為一種流行的伺服器端腳本語言,提供了強大的正規表示式功能,可以輕鬆實現中文替換。本文將分享一些在PHP中使用正規實現中文替換的技巧,同時提供具體的程式碼範例。 1.使用preg_replace函數實作中文替換PHP中的preg_replace函數可以用來
