一分鐘複習正則

在平時的工做中經常會碰到正則,可是我發現,每次都忘記該怎麼去寫,因此在這裏稍微複習總結一下

先看題

/* 題目一 */
var str1 = '123456765464153513566'
// 分割數字每三個以一個逗號劃分(從後往前)
// 如1234 -> 1,234


/* 題目二 */
var str2 = "get-element-by-id"
// 將-的命名方式改成小駝峯
// 指望結果getElementById


/* 題目三 */
var str3 = 'getElementById'
console.log(str3.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase())
// 寫出運行結果

看完這三個題目,你是否有想法,下面公佈答案git

// 題目一
console.log(str1.replace(/(\d)(?=(\d{3})+$)/g,'$1,'))
// 123,456,765,464,153,513,566

// 題目二
console.log(str2.replace(/-\w/g, ($0) => {
    return $0.slice(1).toUpperCase()
}))
// getElementById

// 題目三
// get-element-by-id

若是你的答案所有正確,那麼請忽略下面的內容正則表達式

複習

簡單的匹配規則

  • 如想在apple這個單詞裏找到a這個字符,就直接用/a/這個正則就能夠了
  • 若是想匹配*,須要使用\來轉義去掉其原本的含義,正則就能夠寫成/\*/
  • 有一些字符本不是特殊字符,使用轉義符號就會讓它擁有特殊的含義
特殊字符 正則表達式 記憶方式
換行符 n new line
換頁符 f form feed
回車符 r return
空白符 s space
製表符 t tab
垂直製表符 v vertical tab
回退符 [b] backspace,之因此使用[]符號是避免和b重複

匹配多字符

  • 集合的定義方式是使用中括號[],如/[123]/這個正則就能同時匹配1,2,3三個字符。用/[0-9]/就能匹配全部的數字, /[a-z]/則能夠匹配全部的英文小寫字母
  • 同時匹配多個字符的簡便正則表達式:
匹配區間 正則表達式 記憶方式
除了換行符以外的任何字符 . 句號,除了句子結束符
單個數字, [0-9] d digit
除了[0-9] D not digit
包括下劃線在內的單個字符,[A-Za-z0-9_] w word
非單字字符 W not word
匹配空白字符,包括空格、製表符、換頁符和換行符 s space
匹配非空白字符 S not space

重複匹配

  • 元字符 ? 表明了匹配一個字符或0個字符, 例匹配 colorcolour 這兩個單詞, 就能夠寫爲 /colou?r/
  • 元字符 * 用來表示匹配0個字符或無數個字符, 例匹配 colorcolouuuuuur 就能夠寫爲 /colou*r/
  • 元字符+適用於要匹配同個字符出現1次或屢次的狀況。 colorcolour 這兩個單詞, 若使用 /colou+r/ 來匹配,就只能匹配到colour
  • 匹配特定的次數, 可使用元字符 {} 用來給重複匹配設置精確的區間範圍。如 a 我想匹配3次,那麼我就使用 /a{3}/ 這個正則,或者說 a 我想匹配至少兩次就是用 /a{2,}/ 這個正則。app

    • {x}: x次
    • {min, max}: 介於min次到max次之間
    • {min, }: 至少min次
    • {0, max}: 至多max次
總結
| 匹配規則 | 元字符 |
| :-----:| :----: |
| 0次或1次 | ? |
| 0次或無數次 | * |
| 1次或無數次 | + |
| 特定次數 | {x}, {min, max} |

位置邊界

  • 單詞邊界 \b , 例 The cat scattered his food all over the room. 匹配出全部的單詞cat , 就能夠寫成 /\bcat\b/g
  • 字符串邊界,元字符 ^ 用來匹配字符串的開頭。而元字符$ 用來匹配字符串的末尾。

邊界總結:post

邊界和標誌 正則表達式 記憶方式
單詞邊界 b boundary
非單詞邊界 B not boundary
字符串開頭 ^ -
字符串結尾 $ -
多行模式 m標誌 multiple of lines
忽略大小寫 i標誌 ignore case, case-insensitive
全局模式 g標誌 global

子表達式

分組

全部以 () 元字符所包含的正則表達式被分爲一組,每個分組都是一個子表達式,它也是構成高級正則表達式的基礎。spa

回溯引用

回溯引用(backreference)指的是後面部分引用前面已經匹配到的子字符串。你能夠把它想象成是變量,回溯引用的語法像\1 , \2,....,其中 \1 表示引用的第一個子表達式,\2 表示引用的第二個子表達式,以此類推。而 \0 則表示整個表達式。code

// 例如
// 匹配下面字符串中兩個連續的單詞
// Hello what what is the first thing, and I am am scq000.
var str4 = 'Hello what what is the first thing, and I am am scq000.'

console.log(str4.match(/\b(\w+)\s\1/g))

$1 , $2 ...來引用要被替換的字符串orm

var str = 'abc abc 123';
str.replace(/(ab)c/g,'$1g');
// 獲得結果 'abg abg 123'

若是咱們不想子表達式被引用,可使用非捕獲正則(?:regex)這樣就能夠避免浪費內存。ip

var str = 'scq000'.
str.replace(/(scq00)(?:0)/, '$1,$2')
// 返回scq00,$2
// 因爲使用了非捕獲正則,因此第二個引用沒有值,這裏直接替換爲$2

var str4 = 'scq000 scq001'
console.log(str4.replace(/(scq00)(?:0)/, '$1,$2'))
// 返回 scq00,$2 scq001

前向查找

前向查找(lookahead)是用來限制後綴的。凡是以 (?=regex) 包含的子表達式在匹配過程當中都會用來限制前面的表達式的匹配。例如happy happily這兩個單詞,我想得到以 happ 開頭的副詞,那麼就可使用/happ(?=ily)/來匹配, 就能夠匹配到單詞happilyhapp前綴。若是我想過濾全部以 happ 開頭的副詞,那麼也能夠採用負前向查找的正則/happ(?!ily)/,就會匹配到happy單詞的happ前綴。內存

後向查找

後向查找(lookbehind)是經過指定一個子表達式,而後從符合這個子表達式的位置出發開始查找符合規則的字串。舉個簡單的例子: applepeople 都包含 ple 這個後綴,那麼若是我只想找到 appleple ,該怎麼作呢?咱們能夠經過限制app這個前綴,就能惟一肯定 ple 這個單詞了。element

var str4 = 'apple people';
console.log(str4.replace(/(?<=ap)ple/,'-'))
// 獲得結果 'ap- people'
// 說明匹配到的是單詞apple的ple

(?<=regex) 的語法就是後向查找regex 指代的子表達式會做爲限制項進行匹配,匹配到這個子表達式後,就會繼續向後查找。另一種限制匹配是利用(?<!regex) 語法,這裏稱爲負後向查找。與正前向查找不一樣的是,被指定的子表達式不能被匹配到。因而,在上面的例子中,若是想要查找 appleple 也能夠寫成/(?<!peo)ple

總結
| 回溯查找 | 正則 |
| :-----:| :----: |
| 引用 | 0,1,2 和 $0, $1, $2 |
| 非捕獲組 | (?:) |
| 前向查找 | (?=) |
| 前向負查找 | (?!) |
| 後向查找 | (?<=) |
| 後向負查找 | (?<!) |

邏輯處理

  • 在正則裏面,默認的正則規則都是的關係
  • [] 內部使用的 ^ 表示非的關係
  • 子表達式匹配的非關係就要用到前面介紹的前向負查找子表達式(?!regex)或後向負查找子表達式(?<!regex)
  • 或關係,一般給子表達式進行歸類使用。好比,我同時匹配a,b兩種狀況就可使用(a|b)這樣的子表達式。

解析開頭的題目

到這裏正則差很少已經複習了一遍,咱們如今再去看前面的三道題

題目一

/* 題目一 */
var str1 = '123456765464153513566'
// 分割數字每三個以一個逗號劃分(從後往前)
// 如1234 -> 1,234
console.log(str1.replace(/(\d)(?=(\d{3})+$)/g,'$1,'))
// 123,456,765,464,153,513,566

解析:\d表示單個數字,(?=(\d{3})+$)是一個前向查找,\d{3})+$表示匹配3位數字一次或者屢次而且以三位數字結尾。連在一塊兒看就是,匹配一個數字,數字後面的數字位數是3的倍數,因此匹配到的數字是3, 6, 5, 4, 3, 3,而後替換爲$1,,故3替換爲3,6替換爲6, ....

題目二

/* 題目二 */
var str2 = "get-element-by-id"
// 將-的命名方式改成小駝峯
// 指望結果getElementById
console.log(str2.replace(/-\w/g, ($0) => {
    return $0.slice(1).toUpperCase()
}))

解析:首先/-\w/g 的意思是匹配全部前面是-單個字符,匹配的結果是-e, -b, -i, 而後取其第二位(也就是將-截取掉),再轉換爲大寫

題目三

/* 題目三 */
var str3 = 'getElementById'
console.log(str3.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase())
// 寫出運行結果
// 答案:get-element-by-id

解析: ([a-z])([A-Z])的意思就是匹配兩個字母,而且第一個是小寫,第二個是大寫,因此匹配到的結果是tE, tB, yI,因爲()表明分組,故$1表明的是匹配到的小寫字母,$2表明的是匹配到的大寫字母

參考: 正則表達式不要背
相關文章
相關標籤/搜索