sharplook做爲專業的日誌採集分析系統,涉及的技術點,從後到前着實很多,內容也較爲複雜。正則做爲日誌解析的手段,起着舉足輕重的做用,在此小生將晦澀難懂的內容,拆解出來以便學習之用。git
維基百科對其的定義是:「正則表達式,又稱正規表示式、正規表示法、正規表達式、規則表達式、常規表示法(英語:Regular Expression,在代碼中常簡寫爲regex、regexp或RE),是計算機科學的一個概念。正則表達式使用單個字符串來描述、匹配一系列匹配某個句法規則的字符串。在不少文本編輯器裏,正則表達式一般被用來檢索、替換那些匹配某個模式的文本。」 目前許多程序設計語言都支持利用正則表達式進行字符串操做。簡單地理解就是,正則表達式是用於匹配字符串中字符組合的模式,要麼匹配字符,要麼匹配位置。程序員
目前暫定如下內容將在後期分享於諸君,本篇先介紹正則表達式裏面的字符匹配,實例都將以JavaScript代碼演示,其實正則沒有語言界限,小生也不是強權主義,只是寫來方便罷了。正則表達式
正則表達式不只能夠精確匹配還能夠模糊匹配,假若只有精確匹配,那正則就太弱了,也不值得在此繼續聊下去。編輯器
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
測試以下:設計
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」其中一個。
可視化圖以下:
測試以下:
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.[^]/
的可視化表示以下:
量詞也稱爲重複詞。理解了{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/
。
可視化形式以下:
測試以下:
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 正則表達式迷你書》