首頁 web前端 js教程 詳細講解平衡組_正規表示式

詳細講解平衡組_正規表示式

Jun 28, 2017 pm 01:37 PM
平衡 正規則 表達式

這篇文章主要介紹了正規表示式——詳細講解平衡組,需要的朋友可以參考下

##這篇文章適合你嗎?

要讀懂這篇文章的精髓,你最好要有一點正規匹配原理的基礎。例如".*?"匹配文字內容"asp163",稍懂正規表示式的人都知道可以匹配,但是你知道他的匹配過程嗎?如果你不太清楚,那麼下面的內容,對你來說可能不太適合,或許,看的太吃力且無法領悟平衡組的用法。因此,我建議你先了解正規表示式NFA引擎的匹配原理。想要整理一份易懂易描述的話,的確要花些時間,但我不知道這篇內容會不會達到我預期的效果。慢慢完善吧~(註:這是我2010年寫的,現在拿過來,有時間將自己做為讀者來看本篇文章,修改有問題的地方,並增加些實例,盡量做到通俗易懂。舉個例子吧,如何把“xx aa> yy”這樣的

字符串

#裡,最長的尖括號內的內容捕獲出來?

這裡需要用到以下的語法建構:

(?)

把捕獲的內容命名為group,並壓入堆疊( ?<-group>)

從堆疊上彈出最後壓入堆疊的名為group的捕獲內容,如果堆疊本來為空,則本分組的匹配失敗


(?(group)yes |no) 如果堆疊上存在以名為group的捕獲內容的話,繼續匹配yes部分的表達式,否則繼續匹配no部分
(?!) 順序否定環視,由於沒有後綴表達式,試圖匹配總是失敗
如果你不是一個程式設計師(或者你是一個對堆疊的概念不熟的程式設計師),你就這樣理解上面的三種語法吧:第一個就是在黑板上寫一個(或再寫一個)"group",第二個就是從黑板上擦掉一個"group",第三個就是看黑板上寫的還有沒有"group",如果有就繼續配對yes部分,否則就符合no部分。 我們需要做的是每碰到了左括號,就在黑板上寫一個"group",每碰到一個右括號,就擦掉一個,到了最後就看看黑板上還有沒有——如果有那就證明左括號比右括號多,那匹配就應該失敗(為了能看得更清楚一點,我用了(?'group')的語法):

<         #最外层的左括号
 [^<>]*     #最外层的左括号后面的不是括号的内容
 (
  (
   (?&#39;Open&#39;<) #碰到了左括号,在黑板上写一个"Open"
   [^<>>]*   #匹配左括号后面的不是括号的内容
  )+
  (
   (?&#39;-Open&#39;>) #碰到了右括号,擦掉一个"Open"
   [^<>]*   #匹配右括号后面不是括号的内容
  )+
 )*
 (?(Open)(?!))  #在遇到最外层的右括号前面,判断黑板上还有没有没擦掉的"Open";如果有,则匹配失败
>         #最外层的右括号
登入後複製

我為什麼寫這篇文章

看了上面的介紹,你懂了嗎?在我未理解正規表示式匹配原理之前,請先看上面對於平衡組的介紹,似懂非懂,且只能當做模板記住,而不能靈活運用。因此查閱大量有關正規方面的資料,這裡尤其感謝lxcnn的技術文檔及《精通正則表達式》這本書,讓我對正則表達式有了更深入、更系統的理解,因此,在它們的基礎之上,我就結合自己的學習經驗做個小結,一來做為學習筆記存檔,另外,如果能解決你的疑惑,也是件讓人高興的事。
我先暫不分析上面的程式碼,先來講解一下關於平衡組相關的概念及知識。

下面表達式比對測試工具為:Expresso,本站也提供它的完美破解版下載。

平衡組的概念及作用


平衡組,故名思義,平衡即對稱,主要是結合幾種正則語法規則,提供對配對出現的嵌套結構的匹配。平衡組有狹義與廣義兩種定義,狹義平衡組指
(?Expression)

文法,而廣義平衡組並非固定的語法規則,而是幾種文法規則的綜合運用,我們平時所說的平衡組通常指的是廣義平衡組。本文如無特殊說明,平衡組這種簡寫指的是廣義平衡組。

平衡組的匹配原理平衡組的匹配原理可以用堆疊來解釋,先舉個例子,再根據例子來解釋。

來源字串:

a+(b*(c+d))/e+f-(g/(h-i))*j正規表示式:
( (?\()|(?<−Open>)|[^()])*(?(Open)(?!))\)

需求說明:配對成對出現的()中的內容

輸出:(b*(c+d)) 和(g/(h-i))<br/>我將上面正規表示式程式碼分行寫,並加上註釋,這樣看起來有層次,而且方便<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'> \( #普通字符“(” ( #分组构造,用来限定量词“*”修饰范围 (?&lt;Open&gt;\() #命名捕获组,遇到开括弧“Open”计数加1 | #分支结构 (?&lt;-Open&gt;\)) #狭义平衡组,遇到闭括弧“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代码.现在我们的问题是要提取出其的标签并将其删除掉,以往我们惯用的方法都是直接去取,像[\s\S]+?\,不过问题出来了,我们提取到的不是我们想要的内容,而是

<td id="td2">
<table>
<tr>
<td>snhame</td>
登入後複製

原因也很简单,它和离他最近的标签匹配上了,不过它不知道这个标签不是它的-_-,是不是就是?符号的原因呢,我们去掉让他无限制贪婪,可这下问题更大了,什么乱七八糟的东东它都匹配到了

<td id="td2">
<table>
<tr>
<td>snhame</td>
f


登入後複製

这个结果也不是我们想要的。那么我就用“平衡组”来解决吧。

]*>((?]*>)+|(?<-mm>)|[\s\S])*?(?(mm)(?!))

匹配的结果是

<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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1654
14
CakePHP 教程
1413
52
Laravel 教程
1306
25
PHP教程
1252
29
C# 教程
1225
24
如何用 Golang 正規匹配多個單字或字串? 如何用 Golang 正規匹配多個單字或字串? May 31, 2024 am 10:32 AM

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

如何用php正規取代以什麼開頭的字串 如何用php正規取代以什麼開頭的字串 Mar 24, 2023 pm 02:57 PM

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

php 如何用正規去除中文 php 如何用正規去除中文 Mar 03, 2023 am 10:12 AM

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

php怎麼利用正規匹配去掉html標籤 php怎麼利用正規匹配去掉html標籤 Mar 21, 2023 pm 05:17 PM

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

如何在 Windows 11 ,10 中平衡左/右音訊聲音 如何在 Windows 11 ,10 中平衡左/右音訊聲音 May 02, 2023 pm 04:37 PM

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

如何使用PHP正規表示式驗證URL是否為HTTPS協議 如何使用PHP正規表示式驗證URL是否為HTTPS協議 Jun 24, 2023 am 08:16 AM

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

PHP正規替換實例:快速掌握替換技巧 PHP正規替換實例:快速掌握替換技巧 Feb 29, 2024 pm 06:33 PM

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

使用PHP正規實現中文取代功能的技巧分享 使用PHP正規實現中文取代功能的技巧分享 Mar 24, 2024 pm 05:57 PM

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

See all articles