正則表達式-基礎知識Review

来源:https://www.cnblogs.com/lalalagq/archive/2018/10/07/9750510.html
-Advertisement-
Play Games

正則表達式(Regular Expression)是電腦科學的一個概念。 正則表達式使用單個字元竄來描述、匹配一系列符合某個句法規則的字元竄。 在很多文本編輯器里, 正則表達式通常用來被檢索替換哪些符合某個模式的文本。 "正則表達式實例" 創建 JavaScript通過內置對象 RegExp支持正 ...


正則表達式(Regular Expression)是電腦科學的一個概念。 正則表達式使用單個字元竄來描述、匹配一系列符合某個句法規則的字元竄。 在很多文本編輯器里, 正則表達式通常用來被檢索替換哪些符合某個模式的文本。

正則表達式實例

創建

JavaScript通過內置對象 RegExp支持正則表達式, 有兩種方式創建正則表達式對象, 如果我們想匹配字元竄中<%xxx%>兩個百分號分割的字元竄可以這麼寫。

  • 構造函數

var regExp = new RegExp('&lt;%[^%&gt;]+%', 'g');
  • 字面量

var regExp = /&lt;%[^%&gt;]%&gt;/g;

最後的g代表全局, 還有幾個修飾符

RegExp實例對象有五個屬性

  1. g: global, 全文搜索,不添加的話搜索到第一個結果停止搜索。
  2. i: ignore case, 忽略大小寫,預設大小寫敏感。
  3. m: multiple lines, 多行搜索。
  4. lastIndex: 是當前表達式模式首次匹配內容中最後一個字元的下一個位置,每次正則表達式匹配成功匹配時, lastIndex屬性值都會隨之改變。
  5. sourse:正則表達式的文本字元竄。

除了正則表達式編譯為內部格式從而使執行更快的compile()方法, 對象還有兩個我們常用的方法。

元字元

正則表達式讓人望而卻步的一個重要原因就是轉譯字元太多, 組合非常多, 但是正則表達式的元字元(在正則表達式中具有特殊意義的專用字元,可以用來規定其前導字元)並不多



() [] {} \ ^ $ | ? * + .

並不是每個元字元都有特定的意義,在不同的組合中元字元有不同的意義, 分類看一下

  • t 水平製表符 tab
  • r 回車符 carriage return
  • n 換行符 newline
  • f page feed 換頁符
  • cX 與X對應的控制字元(Ctrl + X )
  • v 垂直製表符
  • 0 空字元

字元類

一般情況下正則表達式一個字元(轉譯字元算一個) 對應字元竄一個字元,表達式 abt 的含義


ab水平製表符

但是我們可以使用元字元[]來構建一個簡單的類, 所謂類是指,符合某些特征的對象, 是一個泛指,而不是特指某個字元了, 我們可以使用表達式[abc], 把字元a或b或c歸為一類,表達式可以匹配這類的字元。

字元類取反

元字元[]組合可以創建一個類,我們還可以使用元字元^創建反向類/負向類,反向類的意思是不屬於XXX類的內容, 表達式1表示不是字元a或b或c的內容。

範圍類

按照上面的說明如果希望匹配單個數字那麼表達式是這樣的


[0123456789]

如果是字母那麼。。。 好麻煩, 正則表達式還提供了範圍類,我們可以使用x-y來連接兩個字元表示從x到y的任意字元, 這是個閉區間, 也就是說包含x和y本身, 這樣匹配小寫字母就很簡單了。


[a-z]

預定義類

剛纔使用正則我們創建了幾個類,來表示數字,字母等,但這樣寫很麻煩,正則表達式為我們了幾個常用的預定義類來匹配常見的字元。

字元 等價類 含義
. [^rt] 除了回車符和換行符之外的所有字元
d [0-9] 數字字元
D [^0-9] 數字字元
s [\t\n\x0B\f\r] 空白符
S [^t\n\x0B\f\r] 非空白符
w [a-zA-Z_0-9] 字母,數字,下劃線
W [^a-zA-Z_0-9] 非字母,數字,下劃線

有了這些預定義類, 寫一些正則就很方便了, 比如我們希望匹配一個 ab + 數字 + 任意字元的字元竄, 就可以寫了abd.

可以把正則表達式,想象成一種模式,字元竄匹配正則表達式定義的模式的結果


string.match(regExpPattern)

邊界

正則表達式還提供了幾個常用的邊界匹配字元。

字元 含義
^ 以xxx開頭, ^ 開頭的匹配參照對象是整個字元竄
$ 以xxx結尾, $ 結尾的匹配參照對象也是整個字元竄
b 單詞邊界, '-'也是單詞邊界!
B 非單詞邊界

^ 開頭的匹配參照對象是整個字元竄,
$ 結尾的匹配參照對象也是整個字元竄,
限制的是整個字元竄。

var regExpPattern = /^h\dm/g;
'h2m h3m h2m'.match(regExpPattern); // h2m, 記住這是以整個字元竄去匹配的

//同理

var regExpExpPattern = /h\dm$/g;
'h2m h3m h3m'.match(regExpPattern); // h3m

//使用場景 手機號匹配

'13423454234'.match(/^1\d{10}$/g)

量詞

之前,介紹的方法都是一一匹配,如果希望匹配一個連續20次數字的字元竄難道我們需要寫成這樣?


\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d..

為此正則表達式引入了一些量詞

字元 含義
? 出現零次或一次(最多出現一次)
+ 出現一次或多次(至少出現一次)
* 出現零次或多次(任意次)
{n} 出現n次
{n,m} 出現n到m次
{n,} 至少出現n次
{,m} 最多出現m次

var regExp = /w+\bBryon/

regExp.test('hi Bryon'); // true

regExp.test('Welcome Byron'); // true

regExp.test('Byron'); //false


//匹配帶有3到1個小數的數字
var reg = /\d+\.d{1,3} 

貪婪模式與非貪婪模式

看了量詞的介紹,也許愛思考的同學會想到關於匹配原則的一些問題, 比如{3,5} 這個量詞, 要是在句子中出現了十次, 那麼他是每次匹配三個還是五個,反正3,4,5都滿足3~5的條件。

量詞在預設下是儘可能多的匹配的,也就是大家常說的貪婪模式。


// ['12345','6789'];
'12345679'.match(/\d{3,5}/g); 

既然有貪婪模式,那麼肯定會有非貪婪模式,讓正則表達式儘可能少的匹配,u額就是說一旦成功匹配不再繼續嘗試,做法很簡單, 在量詞後加上?即可


//['123','456','789']

'123456789'.match(/\d{3,5}?/g);

分組

有時候希望使用量詞的時候匹配多個字元,而不是像上面例子只是匹配一個,比如希望匹配Byron出現20次的字元竄,寫成Byron{20}的話匹配的是Byro+n出現20次。


//寫成Byron{20}的話匹配的是Byro+n出現20次。
/Byron{20}/g

怎麼把Byron作為一個整體呢? 使用()就可以達到此目的,在正則中成為分組。


//分組在regExp.exec(stringObj)中會單獨顯示在返回結果中。

(Byron){20}

或 |

如果希望匹配Byron或Casper出現20次該怎麼辦呢? 可以使用字元| 達到或的功效


(Byron|Casper){20}

使用分組的正則表達式會把匹配項也放到分組中,預設是按數字編號分發的,可以根據編號獲得捕獲的分組內容,這在一些希望具體操作第幾個匹配項的函數中很有用。


// Group 1 : Byron , Group 2: ok
(Byron).(ok)

分組嵌套

如果有分組嵌套的情況,外面的組的編號靠前


// group 1: (^|%&gt;)[^\t]*, Group 2: (^|%&gt;)
((^|%&gt;)[^\t]*)

忽略分組

有時候我們不希望捕獲某些分組,只需要在分組內加上?: 就可以了, 這並不意味著該分組內容不屬於正則表達式,只是不會給這個分組加編號而已。


(?:Bryon).(ok)

前瞻

表達式 含義
exp1(?=exp2) 匹配後面是exp2的exp1
exp1(?!exp2) 匹配後面不是exp2的exp1

var regExp = /good(?=Byron)/;

regExp.exec('goodByron123'); // ['good']
regExp.exec('goodCapser123'); // null

通過上面例子可以看出exp1(?=exp2)表達式, 但只有其後面內容是exp2的時候才會匹配,也就是兩個條件,exp1(?!exp2)比較類似。

正則表達式相關的方法

  • RegExp.prototype.test(str)

該方法用於測試字元竄參數中是否匹配正則表達式模式,如果存在則返回true,否則返回false。


var reg = /\d+\.\d{1,2}$/g;

reg.test('123.45'); // true
reg.test('0.2');  // true

reg.test('a.34'); //false
reg.test('34.5678'); //false

//判斷手機號是否正確
function isPhoneNum(phoneNum) {
    var phoneNumberTester = /^1\d{10}$/;
    return phoneNumberTester.test(phoneNum);
}
  • RegExp.prototype.exec(str)

該方法用於正則表達式模式在字元竄中運行查找,如果exec()找到匹配的文本,則返回一個結果,否則返回null

除了數組元素和length屬性之外, exec()方法返回對象還包括兩個屬性。

  1. index屬性聲明的是匹配文本的第一個字元的位置。
  2. input屬性則存放的是被檢索的字元竄string。

非全局調用

調用非全局的RegExp對象的exec()時,返回數組的第一個元素是與正則表達式相匹配的文本,第二個元素是與RegExpObject的第一個子表達式相匹配的文本(如果有的話), 第三個元素時與RegExp對象的第二個子表達式相匹配的文本(如果有的話),以此類推。

全局調用

調用全局的RegExp對象的exec()時,它會在RegExp實例的lastIndex屬性指定的字元處開始檢索字元竄string

  1. 當exec()找到了與表達式相匹配的文本時, 在匹配後, 它將把RegExp實例的lastIndex屬性設置為匹配文本的最後一個字元的下一個位置。可以通過反覆調用exec()方法來遍歷字元竄中的所有哦匹配文本。
  2. 當exec()再也找不到匹配的文本時,它將返回null,並把lastIndex屬重置為0。

var reg = /\d/g;

var r =  reg.exec('a1b2c3');

console.log(r);

console.log(reg.lastIndex); // 2

r = reg.exec('a1b2c3');

console.log(reg.lastIndex); // 4

var reg = /\d/g;

while (r = reg.exec('a1b2c3')) {
    console.log(r.index + ':' + r[0])
}

//1:1 , 3:2, 5:3
  • String.prototype.search(reg)

search()方法用於檢索字元竄中指定的子字元串,或檢索與正則表達式相匹配的子字元竄。

search()方法不執行全局匹配,它將忽略標誌g, 它同時忽略正則表達式對象的lastIndex屬性,並且總是從字元竄的開始進行檢索,這意味著它總是返回字元竄的第一個匹配的位置。

  • String.prototype.match(reg)

match()方法將檢索字元竄,以找到一個或多個與regexp匹配的文本。但regexp是否具有標誌g對結果影響很大。

非全局調用

如果regexp沒有標誌g,那麼match()方法就只能在字元竄中執行一次匹配。如果沒有找到任何匹配的文本,match()將返回null。否則它將返回一個數組,其中存放了與它找到的匹配文本有關的信息。

該數組的第一個元素存放的是匹配文本,而其餘的元素存放的是與正則表達式的子表達式匹配的文本。除了這些常規的數組元素之外,返回的數組還含有兩個對象屬性。

  1. index屬性聲明的是匹配文本的起始字元在字元竄中的位置。
  2. input屬性聲明的是對stringObject的引用。
  • String.prototype.replace(reg, replaceStr|| function callback())

關於string對象的replace方法, 我們最常用的是傳入兩個字元竄的做法,但這種做法有個缺陷,只能replace一次。



'abcabcabc'.replacce('bc', 'X') //aXabcabc

replace方法的第一個參數還可以傳入RegExp對象,傳入正則表達式可以使replace方法更加強大靈活


'abcabcabc'.replace(/bc/g, 'X'); //aXaXaX
'abcabcabc'.replace(bc/gi, 'X'); // aXaXaX

如果replace方法的第一個參數傳入的是帶分組的正則表達式,我們在第二個參數中可以使用$1...$9來獲取相應分組內容, 比如希望把字元竄1<%2%>34>%567%>89的<%x%>換為&dollar;#x#$, 我們可以這樣

'1<%2%>34>%567%>89的<%x%>'.replace(/<%(d+)%>)/g, '@#$1#@');
// 1@#2#@34@#567#@89

當然還有很多方式可以達到這一目的,這裡只是演示一下利用分組內容,我們在第二個參數中使用@#&dollar;1#@, 其中$1表示被捕獲的分組內容弄, 在一些js模板函數中可以經常見到這種方式替換字元竄。

可以通過修改replace方法的第二個參數,使replace更加強大,在前面的介紹中,只能把所有匹配替換為固定內容,但如果我希望把一個字元竄中所有數字,都用小括弧包起來該怎麼弄?


'2398sdadads1smdsa3mmm23mmmbb'.replace(/\d+/g, function(matchedStr, groupContent$, index, strObj ) {
    return '(' + matchedStr + ')';
})

把replace方法的第二個參數傳入一個function,這個function會在每次匹配替換的時候調用,算是個每次替換的回調函數,我們使用了回調函數的第一個參數,也就是匹配內容,其實回調函數一共有四個參數。

  • 第一個參數很簡單,是匹配字元竄。
  • 第二個參數是正則表達式分組內容,沒有分組則沒有該參數。
  • 第三個參數是匹配項在字元竄中的index。
  • 第四個參數則是原字元竄。

例子


'2398rsjdhahd2131kksdajdj23'.replace(/\d+/g, function(matchedSubStr,index, strObj) {
    console.log(matchedSubStr + '\t' + index + '\t' + strObj);
    return '(' + matchedSubStr +')';
})

//2398 0    2398rsjdhahd2131kksdajdj23    
//2131 12    2398rsjdhahd2131kksdajdj23    
//23 24 2398rsjdhahd2131kksdajdj23    

這是沒有分組的情況,列印出來的分別是匹配內容、匹配項index和原字元竄,看個有分組的。


'&lt;%1%&gt;&lt;%2%&gt;&lt;%3%&gt;'.replace(/&lt;%([^%&gt;]+)%&gt;/g, function(matchedStr, group, index, thisStrObj) {
    console.log(matchedStr + '\t' + group + '\t' + index + '\t' + thisStrObj);
    return group;
})

//&lt;%1%&gt;    1    0    &lt;%1%&gt;&lt;%2%&gt;&lt;%3%&gt;
//&lt;%2%&gt;    2    5    &lt;%1%&gt;&lt;%2%&gt;&lt;%3%&gt;
//&lt;%3%&gt;    3    10    &lt;%1%&gt;&lt;%2%&gt;&lt;%3%&gt;
//"123"
  • String.prototype.split(reg)

使用split方法把字元竄分割為字元數組


'a,b,c,d'.split(',');
// ['a','b','c','d']

和replace方法類似,在一些複雜的分割情況下我們可以使用正則表達式解決


'a1b2c3d'.split(/\d/); // ['a','b','c','d']

  1. abc

原文地址:https://segmentfault.com/a/1190000016599340


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.環境準備 RHEL7.4(最小化安裝) 64bit 2G 記憶體 (1G 記憶體編譯將近一個小時) 磁碟空間 15G 以上。 配置為本地yum 源 從MySQL5.7版本開始,安裝MySQL需要依賴 Boost 的C++擴展,而且只能是 1.59.0 版本; 2.cmake簡介 從mysql5.5起 ...
  • 大數據又稱黑暗數據,是指人腦無法處理的海量數據聚合成的信息資產,在民生、IT、金融、農業、通信等方面都有廣泛應用。未來5年大數據行業呈井噴趨勢,人才需求火爆,2018年大數據人才缺口更是高達900萬。以後想要做大數據相關的工作,需要學習哪些技術知識? 羅馬不是一天建成的,大數據工程師也不是短時間能鍛 ...
  • RDB RDB是將當前數據生成快照保存到硬碟上。 RDB的工作流程: 1. 執行bgsave命令,Redis父進程判斷當前是否存在正在執行的子進程,如RDB/AOF子進程,如果存在bgsave命令直接返回。 2. 父進程執行fork操作創建子進程,fork操作過程中父進程被阻塞。 3. 父進程for ...
  • 本文對Flutter的29種佈局控制項進行了總結分類,講解一些佈局上的優化策略,以及面對具體的佈局時,如何去選擇控制項。 ...
  • 本文主要介紹Flutter佈局中的FittedBox、AspectRatio、ConstrainedBox,詳細介紹了其佈局行為以及使用場景,並對源碼進行了分析。 ...
  • js中innerHTML與innerText的用法與區別 用法: <div id="test"> <span style="color:red">test1</span> test2 </div> 在JS中可以使用:test.innerHTML: 也就是從對象的起始位置到終止位置的全部內容,包括Ht ...
  • 在大家在網上平常瀏覽網頁的時候,想必各位都會看到選項卡功能,在這裡給大家詳解一下用原生js、jQuery如何來寫一些基本的選項卡 話不多說,先給各位看一下功能圖: 好了,下邊開始寫代碼了: HTML代碼: CSS代碼: *{ margin: 0; padding: 0; } ul{ overflow ...
  • react將dom解耦,不用直接操作dom,使用了狀態機制,當狀態改變時視圖就會相應更新。我們知道在react中,父組件可以將一些狀態傳遞給子組件,讓子組件的視圖相應更新,這時我們會發現,只有有關聯的組件才可以依次傳遞,那些沒有父組件與子組件關係的組件,這些組件之間的某些狀態是共用的,這時就需要re ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...