正則表達式工做中一直在使用,可是沒有系統的總結過,今天就從小白的角度梳理一下正則表達式的使用,主要關注的是正則的思想java
邊寫邊聽五月天的派對動物。學會了正則省下的時間就能夠去party了 ^_^node
咱們先來看看正則表達式的概念,畢竟正則的語法、使用都是圍繞着它要解決的問題來的。正則表達式
wikipedia定義:編程
正則表達式(英語:Regular Expression,在代碼中常簡寫爲regex、regexp或RE), 又稱正規表示式、正規表示法、正規表達式、規則表達式、常規表示法, 是計算機科學的一個概念。正則表達式使用單個字符串來描述、匹配一系列匹配某個句法規則的字符串。 在不少文本編輯器裏,正則表達式一般被用來檢索、替換那些匹配某個模式的文本。
首先,正則表達式是一個字符串組成的模式,用來匹配一個字符串,通常用在檢索,替換裏,也常常用來校驗一些字符模式,檢驗是否匹配一個給定的規則。編程語言
正則表達式使用字符串來描述字符串,也就是說跟編程語言,正則表達式是有本身的關鍵字
的,學會這些關鍵字是咱們入門正則的第一步,而後在使用中領會正則表達式的思想,一步步進階。編輯器
首先要明確一點,正則引擎在匹配時是一個字符一個字符的匹配的,跟咱們日常印象中一串一串匹配的思惟是不一樣的,這個須要咱們時刻牢記。工具
咱們首先來看一下匹配一個字符的關鍵字:日誌
元字符 | 名稱 | 含義 |
---|---|---|
. | 點號 | 匹配任意一個字符 |
[……] | 字符組 | 匹配組內的單個字符 |
[^……] | 排除性字符組 | 匹配單個未列出的字符 |
\meta | 轉義字符 | 特殊含義或轉義元字符 |
英文點號能夠匹配任意字符,可是不包括換行符,也就是說匹配到換行點號就匹配失敗了,咱們可使用\n
來匹配換行符,在java中也有MULTI_LINES
來指定讓點號匹配到換行符code
若是咱們想匹配一個文本形式的點號怎麼弄呢,可使用反斜線\
來轉義關鍵字,這樣就能夠匹配一個點號,而不是匹配任意字符的關鍵字點號了。regexp
關於字符組須要說明一點,可使用-
來描述一個範圍,好比咱們想匹配數字,咱們能夠寫一個全列[0123456789]
,也可使用[0-9]
,字符也是同樣[a-zA-z]
匹配英文大小寫的26個字母,若是咱們想匹配橫槓怎麼辦呢?只有一個辦法,那就是把它寫在緊跟左中括號後面,[-a-z]
匹配橫槓和a-z的全部字母,若是寫在中間是會被當成關鍵字來解析的。
有了匹配單個字符的關鍵字,匹配多個就要用到計數元字符,經常使用的有下面這些:
元字符 | 名稱 | 含義 | 區間表示 |
---|---|---|---|
? | 問號 | 匹配至多一次 | {0,1} greedy的 |
* | 星號 | 匹配任意屢次,也能夠不匹配 | {0,} |
+ | 加號 | 匹配至少一次 | {1,} |
{min, max} | 區間 | min <=匹配次數 <= max | grep默認不支持{元字符,可使用-E選項 |
*?,+?,??,{min,max}? | 忽略優先量詞 | 匹配儘量少的內容 | |
*+, ++, ?+ {min,max}+ | 佔有優先量詞 | 匹配內容後不會交還,相似固化分組 |
?*+
這三個元字符是可使用{}
來模擬的,不過在一些正則流派裏不支持{}
元字符,咱們只能使用這三個。
在爲加?
的量詞上,前四個都是貪婪匹配的,也就是說他們會匹配儘量多的字符,在匹配失敗的時候纔會中止,這有時候頗有用,但有時候會讓咱們沒有通過深思寫出來的正則匹配到錯誤的內容。第四列在量詞後面加了?
則正相反,它會匹配儘量少的內容,是先爲人後爲幾的,這兩種方式的區別咱們後面再講,這跟表達式引擎的遞歸與回溯有關。
最後一列是佔有優先量詞,這個概念是在貪婪的基礎上加了鐵公雞屬性(佔有),也就是說經它匹配過的字符就是它的了,不會再吐出來。後面咱們在講回溯跟固化分組時是再來回顧這個佔有優先量詞。
上面二者組合能夠匹配大部分字符了,不過有些寫起來很繁瑣,所以正則爲咱們提早定義好了一些簡寫,使用時能夠減小表達式長度。
元字符 | 名稱 | 含義 |
---|---|---|
\s | [ \f\v\t\n\r] | 匹配空格,製表符,回車、換行 |
\S | 除\s以外的任何字符 | |
\w | [a-zA-Z0-9_] | 匹配一個單詞 |
\W | [^a-zA-Z0-9] | 匹配除\w外的任何字符 |
\d | [0-9] | 數字 |
\D | [^0-9] | 非數字 |
注:相同字母的小寫跟大寫在這是互補的,也就是互爲補集,不過須要注意一點,在這裏面沒有包含Unicode字符,不一樣的正則引擎對這些有不一樣的實現,譬如\d
有的正則引擎能夠匹配Unicode中的數字,也就是說中文六
也是有可能匹配的,這個能夠參考各自的語言工具書(不過通常這樣用沒啥問題)。
我這裏使用nodepad++來練習正則表達式,Linux下有些字符處理起來比較麻煩,Java寫起來又太囉嗦,怎麼簡便怎麼來。
找出一段文字中的數字
\d+
或 [0-9]+
這裏使用加號是由於數字至少出現一次纔是合法的,若是使用*
則能夠匹配任意位置,由於*
能夠不匹配任何字符
日誌裏常根據關鍵字和id來定位,通常如何使用呢?
假設關鍵字爲keyword
, id爲13235413
,而且id在後面,咱們可使用keyword.*13235413
來匹配含有這個模式的一行日誌,這裏加不加問號對咱們沒有影響
找出一行裏含有至少10個單詞的行,假設單詞以空格分割
這
是
自
己
的
思
考
線
不存在惟一的答案,我是這樣寫的(\w++ *){10,}
,第一次寫成了(\w+ *){10,}
,也就是沒有使用佔有優先量詞,這個表達式是不符合要求的,你們能夠試一下,而後想一想,後面咱們會在涉及到回溯與固化分組相關的時候就能夠明白了。