【JavaScript】正規表示式

TypantK發表於2019-03-02

原貼:https://juejin.im/post/582dfcfda22b9d006b726d11

正規表示式圖形演示:https://regexper.com/


 

手機號正則

/^1[34578][0-9]{9}$/

tips:以1開頭,第二位為3 4 5 7 9 其中一個,以9位(本身1次加重複8次)0-9數字結尾。

 

單詞邊界

/bisb/

tips:is前後都是單詞的邊界,比較晦澀難懂?感受下兩者的區別,b 會方道語法部分講解

 

URL分組替換

/http:(//.+.jpg)/

看不懂的不要慌語法部分後面會有介紹,這裡只是展示利用視覺化的圖形幫助我們理解正規表示式,可以回來再看木有關係。

正規表示式中括號用來分組,這個時候我們可以通過用$1來獲取 group#1 的內容。

說下這個正則的意義,如果網站用了https,網站引用靜態資源也必須是https,否則報錯。如果寫成 // 會自動識別 http 或者 https。

 

日期匹配與分組替換

/^d{4}[/-]d{1,2}[/-]d{1,2}$/

這個正則比較複雜,畫符唸咒的地方太多了,一一分析:

1、Start of line 是由^生效的表示以此開頭

2、對應結尾End of line 由$生效表示以此結尾

3、接著看digit 由 d 生效表示數字

4、3times 由{4} 生效表示重複4次

開始的時候有疑問,為什麼不是 4times,後來明白作者的用意,正規表示式是一個規則,用這個規則去從字串開始匹配到結束(注意計算機讀字串可是不會分行的,都是一個串,我們看到的多行,人家會認為是個 t )這裡設計好像小火車的軌道一直開到末尾。digit 傳過一次,3times表示再來三次迴圈,共4次,後面的once同理。 自己被自己囉嗦到了。

5、接下來,是 one of 在手機正則裡面已經出現了。表示什麼都行。只要符合這兩個都讓通過。

好了這個正則解釋完了,接下來用它做什麼呢?

我們可以驗證日期的合法性。結合URL分組替換所用到的分組特性,我們可以輕鬆寫出日期格式化的方法。

改造下這個正則:

/^(d{4})[/-](d{1,2})[/-](d{1,2})$/

輕鬆的可以拿到 group#1 #2 #3 的內容,對應 $1 $2 $3。

到現在已經能結合圖形化工具看懂正規表示式表示式了,如果想自己寫,還要在正則語法上下點功夫

 

JS中REGEXP物件

Java 通過內建物件RegExp支援正規表示式,有兩種方法例項化RegExp物件。

字面量方法

const reg =/bisb/g

建構函式

const reg = new RegExp('bisb', 'g')

 

正規表示式語法 修飾符(三個 g 、i、m)

修飾符與其他語法特殊,字面量方法聲名的時候放到//後,建構函式宣告的時候,作為第二個引數傳入。整個正規表示式可以理解為正規表示式規則字串+修飾符。

  • g:global 執行一個全域性匹配
  • i:ignore case執行一個不區分大小寫的匹配
  • m:multiple lines多行匹配

修飾符可以一起用。

  1. const reg =/bisb/gim

來說說他們有什麼作用。

有g和沒有g的區別

沒有g只替換了第一個,有g 所有的都換了

 

有i和沒有i的區別

有i忽略大小寫,沒有i嚴格區分大小寫

 

元字元

正規表示式由兩種基本字元組成:

  • 原義字元
  • 非列印字元
  • 元字元 (* + ? $ ^ . | ( ) { } [ ])

原義字元

這個沒什麼好解釋的,我們一直在舉例的 /is/ 匹配字串'is'。

將下一個字元標記為一個特殊字元、或一個原義字元、或一個向後引用、或一個八進位制轉義符。例如,n”匹配字元“n”。“n”匹配一個換行符。序列“”匹配“”而“(”則匹配“(”。

非列印字元

非列印字元,以n為例。

其他的在前端引用比較少,應該在後端處理文字檔案的時候會用到。

字元類 []

在前面的手機號正則例子?中,我們已經使用過[] /^1[34578][0-9]{9}$/

[34578]表示34578任意一個數字即可。在日期匹配與分組替換例子?中 /^d{4}[/-]d{2}[/-]d{2}$/ 表示符合 / - 都可以

字元類取反 [^]

表示不屬於此類

空格也不屬於,好多狗

範圍類[-]

正規表示式支援一定範圍規則比如 [a-z] [A-Z] [0-9] 可以連寫[a-z0-9] 如果你只是想匹配-在 範圍類最後加-即可。請看例項。

預定義類

常用為了方便書寫。

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

邊界

邊界顧名思義即定義匹配的邊界條件,上面基本都在前面的例子碰到了,這裡演示下b與B 的區別。

量詞

如果沒有量詞,要匹配4位數字這樣寫就可以/dddd/, 如果匹配50位100位呢?那不是要瘋掉了?

有了量詞,就可以這樣寫/d{100}/, 量詞的使用我們在手機號中使用過,表現在視覺化中就是迴圈多少次。

湊一個上面都包含的例項/d?@d*@d+@d{10}@d{10,20}@d{10,}@d{0,10}/。

貪婪與懶惰(非貪婪)

正規表示式預設會匹配貪婪模式,什麼是貪婪模式呢?如其名儘可能多的匹配。我們看個例子。

  1. /d{3,6}/

貪婪模式下,匹配的了最多的情況。

與貪婪對應就是懶惰模式,懶惰對應的就是匹配的儘可能少的情況。如何開啟懶惰模式? 在量詞後面加?。繼續上面的例子。

/d{3,6}?/

如果想知道,正規表示式是如何匹配量詞的,請看進階正規表示式文中有介紹,正則是如何回溯的。

分組與反向引用

分組,又稱為子表示式。把正規表示式拆分成小表示式。概念枯燥,說個例子為嘛用分組:

不分組

/abc{2}/

量詞僅作用到最後的c。

分組

/(abc){2}/

注意這裡 group #1,分組雖然和運算子() 很像,但是分組在正規表示式中,注意理解組的含義。經常有人濫用分組。

/^(http|https)/ 真的需要這樣麼?其實 /^https?/就可以了,你正則寫的特別長的時候,會出現一堆沒用的結果,看著都頭疼吧。

分組往往和反向引用一起使用,別被概念嚇到:當一個正規表示式被分組後,每個分組自動被賦予一個組號,一左到右分別是 $1 $2…

再把之前的例子拿出來。

/^(d{4})[/-](d{2})[/-](d{2})$/

輕鬆的可以拿到 group#1 #2 #3 的內容,對應 $1 $2 $3。

如果在反向引用中不想捕獲年該如何操作? 加上 ?:即可。

/^(?:d{4})[/-](d{2})[/-](d{2})$/

前瞻

這部分為進階部分—選看。

正規表示式中有前瞻(Lookahead)和後顧(Lookbehind)的概念,這兩個術語非常形象的描述了正則引擎的匹配行為。需要注意一點,正規表示式中的前和後和我們一般理解的前後有點不同。一段文字,我們一般習慣把文字開頭的方向稱作“前面”,文字末尾方向稱為“後面”。但是對於正規表示式引擎來說,因為它是從文字頭部向尾部開始解析的(可以通過正則選項控制解析方向),因此對於文字尾部方向,稱為“前”,因為這個時候,正則引擎還沒走到那塊,而對文字頭部方向,則稱為“後”,因為正則引擎已經走過了那一塊地方。

注意:後顧效能損耗比較大,js只支援前瞻(知乎上看到的,具體原因不詳)。

上面的比較概念話,嘗試用大白話講講,就說皇上選妃吧,先行條件得是美女吧,長得“如花”那樣皇上可不要,漂亮這關過了,皇上想要這個美女也不行,皇室有規矩,必須是貴族血統。

那麼“漂亮”就是正常的匹配,匹配到了,還得看看家室是不是貴族。"貴族"相當於前瞻條件。

前瞻分兩種一種是正向前瞻(?=xxx), 另一種是負向前瞻(?!xxx)

是不是很簡單?那我們來玩個好玩的。

題目:如何將'123456'轉成貨幣帶逗號的。'123,456'。這個是很常規格式化金額的需求。

如果在沒有學習正則之前,我的思路是:

  • 字串轉陣列
  • 反轉陣列
  • 每隔三個新增個逗號
  • 新增完了反轉陣列
  • 陣列轉字串

好累~~~今天學習了正則,可以一步到位:

'123456789'.replace(/(d)(?=(?:d{3})+$)/g, '$1,')

相關文章