正則表達式--內功心法

[TOC]javascript


開發過程當中,不少人止於正則,搜於網絡。正則雖小,意義頗大。幾乎全部開發語言都提供支持, 它始於仿生學(神經元描述)符號描述,崛起於各操做系統,附生於編輯器中,欣欣向榮,如日中天。前端

場景

  • 千分位

某大廠有這麼一道題目,具備開放性。 大數字以千分位隔開即生活場景中的帳戶金額,怎麼作? 仁者見仁智者見智,辦法總比問題多,然而一條簡單正則輕鬆解決。java

正則表達式:/(\d{1,3})(?=(\d{3})+$)/g

如:linux

"1111234334".replace(/(\d{1,3})(?=(\d{3})+$)/g,"$1,")
  • 支付弱密碼校驗

不少場景下,用戶會設置簡單易記密碼,爲了不用戶密碼被撞庫,被不法分子利用,須要在設置時校驗,提示用戶。正則表達式

如123456使用正則校驗網絡

/(0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)){5}/

目的或意義

對字符串進行過濾篩選匹配,獲得預期的值或效果編輯器

概念

對字符串和特殊符號操做的邏輯公式操作系統

應用場景

表單校驗,條件搜索查詢,數據替換等code

linux 裏面不少地方都用到對象

sed 's/pattern/replacement/flag' file
awk '/pattern/program' file

正向預查

在任何匹配 pattern 的字符串開始處匹配查找字符串。

預查是非捕獲特性,JAVASCRIPT不支持反向預查

正向正預查

?:

window(?:10|7) 能夠匹配window10 或 window7 ``` javascript /window(?:10|7)/.test("window10") //true

匹配過程是如何的呢?

字符串從左到右,遊標起始於字符串開始部分的左側,正則表達式的w與字符串w匹配,匹配成功後,遊標移動到w右側,而後匹配i,匹配成功後,遊標繼續遊走,以此類推直到遊標停留到字符串末尾

?=

/window(?=7)/.test("window7") //true

匹配過程又如何呢?

遊標由字符串的最左側開始,正則表達式以此匹配直到window的右側,此時遊標停留,正則繼續匹配,當匹配到7的時候,匹配成功。因爲遊標停留在7的左側(即w的右側),所以獲得的匹配結果是window而不是window7

正向負預查

?!

/window(?!7)/.test("windowXP") //true

此時的匹配過程又該如何 跟上面?=相似,不一樣的是XP與正則中的7不對應時爲匹配成功

反向預查

在任何不匹配pattern 的字符串開始處匹配查找字符串。

反向正預查

/(?<=best)pay/  匹配bestpay

反向負預查

/(?<!best)pay/  匹配alipay

非貪婪模式 VS 貪婪模式

  • 貪婪模式

例如:

javascript /ab*c/.test("abbbc") //匹配abbbc

貪婪模式

過程以下:

遊標從a左側開始,正則與字符串匹配到ab後,b繼續與b匹配,直到c與b匹配,發現不能匹配,因而,選用備選路線,選用用字符串c與正則c匹配,匹配上游標前進到c的右側所有匹配完成

  • 非貪婪模式

例如:

javascript /ab*?c/.test("ac") //匹配ac

非貪婪模式

正則中? 是優先考慮的

過程以下:

遊標從字符串"ac"中a的左側開始,正則a與字符a匹配上,遊標前進到a的右側,此時模式中的"b*?" 與字符"c"匹配不上,因而,選用備用方案,正則會用"c" 與跟 字符串的"c"匹配,匹配上後,遊標移動到末尾,所以匹配的值是ac

執行過程

基於PCRE的正則引擎有一個特色:遞歸和回溯

遞歸

javascript /^c*?d(?=e)/.test("cde") //true, 匹配cd
  1. ^表示起始位置0(即字符串cd的左側)

$表示字符串末尾

  1. "cd"中的c與正則中的c*?進行匹配,遊標繼續前進,
  2. "cd"中的d與c*?匹配不上時,選用備選路線
  3. "cd"中的d與正則中的d對比並匹配上
  4. ?=e不佔用位置可是要校驗e值的存在(即遊標在d右側時,"cde"中e與?=e匹配上,遊標不會移動)

相似?=e這種零位佔用還有^,$

回溯

javascript /tf??a/.test("tea") //false

過程以下:

  1. 由字符串"tea"左側開始,"tea" 的t 與 正則t匹配
  2. 忽略f?? 直接匹配正則a,"tea"的"e" 與 正則表達式中"a" 對比,匹配失敗
  3. 正則表達式回溯到f??, 此時「tea」中的「e」 與正則表達式中「f??「對比,匹配失敗
  4. 正則模式繼續回退,此時正則表達式中t與字符串中」e「比較,匹配失敗

對於??,是可優先忽略的

符號的運算優先級

優先級從高到低

操做符號 描述
\ 轉義符
(), (?:), (?=), [] 圓括號和方括號
*, +, ?, {n}, {n,}, {n,m} 限定符
^, $, \anymetacharacter 位置和順序

金無足赤人無完人

任何東西都得以辯證角度看待,凡是都有好有壞。 雖然正則能夠做爲一種途徑實現業務需求,可是,因爲自身的特性(遞歸,回溯等)會致使執行效果在某些場景下匹配速度較慢,還不如直接使用字符串的搜索。

正則經常使用符號及含義

普通字符

非打印字符

字符 含義 備註
\f 換頁符 等價於 \x0c 和 \cL
\cx 匹配由x指明的控制字符 \cM 匹配一個 Control-M 或回車符
\n 換行符 等價於 \x0a 和 \cJ
\r 匹配一個回車符。 等價於 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、製表符、換頁符等等。 等價於 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。 等價於 [^ \f\n\r\t\v]。
\t 匹配一個製表符。 等價於 \x09 和 \cI。
\v 匹配一個垂直製表符。 等價於 \x0b 和 \cK。

特殊字符

字符 含義 備註
\$ 匹配輸入字符串的結尾位置。 若是設置了 RegExp 對象的 Multiline 屬性,則 $ 也匹配 ‘\n’ 或 ‘\r’。要匹配 $ 字符自己,請使用 \$。
( ) 標記一個子表達式的開始和結束位置。 子表達式能夠獲取供之後使用。要匹配這些字符,請使用 ( 和 )。
* 匹配前面的子表達式零次或屢次。 要匹配 * 字符,請使用 *。
+ 匹配前面的子表達式一次或屢次。 要匹配 + 字符,請使用 +。
. 匹配除換行符 \n以外的任何單字符。 要匹配 .,請使用 \。
[ 標記一箇中括號表達式的開始。 要匹配 [,請使用 [。
? 匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。 要匹配 ? 字符,請使用 \?。
\ 將下一個字符標記爲或特殊字符、或原義字符、或向後引用、或八進制轉義符。 例如, ‘n’ 匹配字符 ‘n’。’\n’ 匹配換行符。序列 ‘\’ 匹配 「\」,而 ‘(’ 則匹配 「(」。
^ 匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。 要匹配 ^ 字符自己,請使用 \^。
{ 標記限定符表達式的開始。 要匹配 {,請使用 \{。
指明兩項之間的一個選擇。

定位符號

用來描述字符串或單詞的邊界

  • ^ > 字符串以何元素開始
  • $ > 字符串以什麼結束
  • \b > 描述單詞以何爲邊界
  • \B > 描述單詞非邊界狀況

限定符號

字符 含義 備註
* 匹配前面的子表達式零次或屢次。 * 等價於{0,}。
+ 匹配前面的子表達式一次或屢次。 + 等價於 {1,}。
? 匹配前面的子表達式零次或一次。 ? 等價於 {0,1}。
{n} n 是一個非負整數。匹配肯定的 n 次。 例如,’o{2}’ 不能匹配 「to」 中的 ‘o’,可是能匹配 「tooth」 中的兩個 o。
{n,} n 是一個非負整數。至少匹配n 次。 例如,’o{2,}’ 不能匹配 「to」 中的 ‘o’,但能匹配 「foooood」 中的全部 o。’o{1,}’ 等價於 ‘o+’。’o{0,}’ 則等價於 ‘o*’。
{n,m} m 和 n 均爲非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。 例如,」o{1,3}」 將匹配 「fooooood」 中的前三個 o。’o{0,1}’ 等價於 ‘o?’。請注意在逗號和兩個數之間不能有空格。

字符簇

字符 含義 備註
\d 匹配一個數字字符。 等價於 [0-9]。
\D 匹配一個非數字字符。 等價於 [^0-9]。
\w 匹配包括下劃線的任何單詞字符。 等價於’[A-Za-z0-9_]’。
\W 匹配任何非單詞字符。 等價於 ‘[^A-Za-z0-9_]’。
\num 匹配 num,其中 num 是一個正整數。對所獲取的匹配的引用。 例如,’(.)\1′ 匹配兩個連續的相同字符。

做者簡介:

就任於甜橙金融信息技術部,負責前端開發工做,前後任職攜程,平安等公司的前端開發工程師職位,喜歡研究新的技術,服務於業務需求,熟練運用Linux/Unix系統命令,以終端爲載體,快速執行操做。

相關文章
相關標籤/搜索