正則表達式之字符匹配

sharplook做爲專業的日誌採集分析系統,涉及的技術點,從後到前着實很多,內容也較爲複雜。正則做爲日誌解析的手段,起着舉足輕重的做用,在此小生將晦澀難懂的內容,拆解出來以便學習之用。git

認識正則

維基百科對其的定義是:「正則表達式,又稱正規表示式、正規表示法、正規表達式、規則表達式、常規表示法(英語:Regular Expression,在代碼中常簡寫爲regex、regexp或RE),是計算機科學的一個概念。正則表達式使用單個字符串來描述、匹配一系列匹配某個句法規則的字符串。在不少文本編輯器裏,正則表達式一般被用來檢索、替換那些匹配某個模式的文本。」 目前許多程序設計語言都支持利用正則表達式進行字符串操做。簡單地理解就是,正則表達式是用於匹配字符串中字符組合的模式,要麼匹配字符,要麼匹配位置。程序員

內容大綱

目前暫定如下內容將在後期分享於諸君,本篇先介紹正則表達式裏面的字符匹配,實例都將以JavaScript代碼演示,其實正則沒有語言界限,小生也不是強權主義,只是寫來方便罷了。正則表達式

  1. 字符匹配
  2. 位置匹配
  3. 分組匹配
  4. 待續....

模糊匹配

正則表達式不只能夠精確匹配還能夠模糊匹配,假若只有精確匹配,那正則就太弱了,也不值得在此繼續聊下去。編輯器

const reg = /hello, world/;
console.log(reg.test('hello ,world'));
// => true

而強大的模糊匹配,有兩個方向上的「模糊」: 橫向模糊和縱向模糊。工具

橫向模糊

橫向模糊指的是,一個正則可匹配的字符串的長度是不肯定的,能夠是多種狀況。學習

其實現的方式是量詞。例如{m,n},表示最少出現m次,最多出現n次。例如正則/ab{2,4}c/表示匹配一個「a」,緊接着匹配2個或者3個或者4個連續的字母「b」,最後匹配字母「c」。測試

可視化圖以下:spa

h-like

測試以下:設計

const reg = /ab{2,4}c/g;
const string = 'abc abbc abbbc abbbbc abbbbbc';
console.log(string.match(reg));
// => ['abc', 'abbc', 'abbbc', 'abbbbc']

正則 /ab{2,4}c/g中的‘g’是正則的修飾符,表示此正則採用全局匹配,按照順序匹配出全部符合正則的字符串,g表示global。日誌

縱向模糊

縱向模糊指的是,一個正則匹配的字符串,當匹配到某一位的字符時,並非一個特定的字符,其有多種可能性。

其實現的方式是字符組。例如[abc],表示匹配的字符多是「a」,「b」,「c」中的一個。 例如/a[123]b/表示匹配的是「a1b」,「a2b」,「a3b」其中一個。

可視化圖以下:

v-like

測試以下:

const reg = /a[123]c/g;
const string = 'a1c a2c a3c a4c';
console.log(string.match(reg));
// => ['a1c', 'a2c', 'a3c'];

字符組


字符組雖然是組的概念,可是隻是表示其中一個字符。

例如[abc],表示匹配其中一個字符,它能夠是「a」,「b」,「c」之一。

範圍表示法

若是字符組中的字符很是多的話,怎麼辦呢?可使用範圍表示法。

例如「1234567abcdefgHIJKLMN」但是表示爲[1-7a-gH-N]。用連字符「-」表示簡寫中間的項。

在這裏「-」表示特殊含義,若是正則匹配須要匹配這個字符,好比匹配「a」,「h」,「-」怎麼辦呢? 能夠寫成[-ah][ah-][a\-h]中的一種,這樣就能夠避免被做爲連字符來處理了。

排除字符組

在縱向匹配中,咱們還會遇到一種狀況,那就是咱們不但願匹配到字符組的任何一個字符。例如不能匹配「a」,「b」,「c」。

此時就出現了排除字符組的概念。例如[^abc],表示匹配除了「a」,「b」,「c」字符以外的任意一個字符。字符組中第一位放^脫字符,表示求反的概念。

固然,也有相應的範圍表示法,例如:[^a-h]

常見的簡寫

有了字符組的概念以後,咱們就很容易理解系統自帶的簡寫方式了。

  • \d: 表示 [0-9]。表示是一位數字。 記憶方式: 其英文是 digit(數字)。
  • \D: 表示 [^0-9]。表示除數字外的任意一個字符。
  • \w: 表示 [0-9a-zA-Z_]。表示數字、大小寫字母和下劃線。記憶方式:w是 word的簡寫,也表示單詞字符。
  • \W: 表示 [^0-9a-zA-Z_]。表示除了數字、大小寫字母和下劃線以外的任意一個字符。非單詞字符。
  • \s: 表示 [\r\v\n\r\f]。表示空白符,包括空格、水平製表符、垂直製表符、換行符、回車符、換頁符。記憶方式: s是 space的首字母,空白字符的單詞是 white space。
  • \S: 表示 [^\r\v\n\r\f],表示非空白符。
  • . : 表示 [^\n\r\u2028\u2029]。通配符,表示幾乎任意字符,除了換行符、回車符、行分隔符和段分隔符除外。記憶方式:想一想省略號 ... 中的每一個點,此處省略了無數個字(什麼狀況均可能發生)。

若是表示任意字符,怎麼辦? 可使用[\d\D][\w\W][\s\S][^]中任何一個。

/\d\D\w\W\s\S.[^]/的可視化表示以下:

simple-alpha

量詞

量詞也稱爲重複詞。理解了{m,n}後,咱們再來記住一些簡寫方式。

簡寫方式

  • {m,}:表示至少出現m次。
  • {m} :表示出現m次,等價於{m,m}
  • ? :表示出現一次或者不出現,等價於{0,1}。記憶方式: 問號的表示意思,有嗎?
  • + :表示出現一個或者屢次,等價於{1,}。記憶方式: 加好是追加的意思,先獲得一個,之後的再追加。
  • * :表示出現任意次數,可能不出現。記憶方式: 比如天上的星星,可能一個沒有,可能只有零星幾個,也可能有無數多。

貪婪匹配與惰性匹配

先看一個簡單的例子:

const reg = /\d{2,5}/g;
const string = '123 1234 12345 123456';
console.log(string.match(reg));
// => ['123', '1234', '12345', '12345']

其中正則/\d{2,5}/表示匹配連續的數字2次到5次。會匹配2位、3位、4位、5位連續數字。

可是其是貪婪的,它會盡量多的匹配。你能給我 5 個,我就要 5 個。你能給我 3 個,我就要 3 個。
反正只要在能力範圍內,越多越好。

可是有時候貪婪並非一件好事(人心不足,蛇吞象)。而惰性匹配,就是儘量少的匹配,例以下:

const reg = /\d{2,5}?/g;
const string = '123 1234 12345 123456';
console.log(string.match(reg));
// => ['12', '12', '34', '12', '34', '12', '34', '56']

其中 /d{2,5}?/ 表示,雖然 2 到 5 次都行,當 2 個就夠的時候,就再也不往下嘗試了。

對惰性匹配的記憶方式是: 量詞後面加個問號,問一問你滿足了嗎,你很貪婪嗎?

多選分支

一個模式能夠實現橫向匹配和縱向匹配,而多分支能夠支持多個子模式任選其一。

具體形式以下(p1|p2|p3),其中p一、p2和p3是子模式,用|(管道符)分隔,表示任選其一。

例如匹配hello或者world,正則式爲/hello|world/

可視化形式以下:

switch-like

測試以下:

const reg = /hello|world/g;
const string = "hello lemon, world is yours!";
console.log(string.match(reg));
// => ['hello', 'world']

須要注意的地方是,he|hello,你想匹配「hello」這個單詞,結果是「he」。

以下實例:

const reg = /he|hello/g;
const string = 'hello';
console.log(string.match(reg));
// => ['he']

若是你的正則改成hello|he。匹配的結果就是「hello」

以下實例:

const reg = /hello|he/g;
const string = 'hello';
console.log(string.match(reg));
// => ['hello']

由此可知,多分支結構匹配也是惰性的,當前面匹配上以後,後面就不在匹配了。

小結

正則表達式是一個優秀程序員的基本技能,自己雖然不是很複雜,但內容卻比較雜亂,能一步一步理清思路是很重要的,本章主要先介紹了字符的匹配,下一章將介紹位置的匹配。

本文中的正則表達式轉化爲關係圖來展現的工具是Regexper

此文主要參考和學習了老姚的《JavaScript 正則表達式迷你書》,內容清晰明瞭,在此很是感謝老姚的 free精神,致敬。

參考文獻

[1] 老姚 著《JavaScript 正則表達式迷你書》

相關文章
相關標籤/搜索