【野路子】正則表達式~極速學習javascript
本教程適合正則新手、初學者、看完能就用的人羣。php
網上的教程太多太多了,零散的也比較多,視頻教程看起來更佳。可是整個過程比較漫長枯燥,可能暫時和你的需求目標不太一致,有些學不致用的樣子。或者是問人、問百度最後搞出來了,可到了下次須要用到的時候,又進入萌逼狀態了。html
若是你停留在這個問題上,這個教程可能對你做用不大。須要瞭解的話,詳細查閱百科。java
這裏只說一點:正則表達式在不少計算機程序設計語言上均可以進行匹配字符串的一種模式。python
每每用到的狀況以下:數據校驗、採集程序、爬蟲程序,或者說我就想從目標數據拿到我想要的信息。正則表達式
若是你作好準備了,那麼如下將以經常使用的兩種語言進行講述。chrome
Js、PHPswift
首先來看個例程:ruby
https://www.oschina.net/函數
如:title、description、keywords
怎麼獲取源碼就不說了,右鍵查看源代碼等,相似問題後面再也不提起。
在線測試正則表達式地址:http://tool.oschina.net/regex/
能夠看到源碼中的目標數據如橫線所標。咱們只須要匹配到對應的內容便可以。
首先將對應的數據信息包括固定數據本來複製出來。
標題:<title>開源中國 - 找到您想要的開源項目,分享和交流</title> 描述:<meta name="description" itemprop="description" content="開源中國 www.oschina.net 是目前中國最大的開源技術社區。咱們傳播開源的理念,推廣開源項目,爲 IT 開發者提供了一個發現、使用、並交流開源技術的平臺。目前開源中國社區已收錄超過兩萬款開源軟件。, 開源中國社區"> 關鍵詞:<meta name="keywords" content="開源,OSC,開源軟件,開源硬件,開源網站,開源社區,java開源,perl開源,python開源,ruby開源,php開源,開源項目,開源代碼">
舉例測試標題,複製到在線測試正則裏面進行調試。
很顯然咱們匹配到結果了,這個正則表達式中能夠認爲不存在任何 正則表達式的語法,剛纔的過程只是至關於 正常的字符串匹配。
咱們繼續,刪除部分數據(刪除可變的數據),用正則表達式語法代替。
正則表達式的書寫原則也就是:用正則語法替換可變的數據
語法:
\s 空格換行等字符
\S 非空格換行等字符
根據這個,那麼咱們將其中的內容替換下。
<title>開源中國 - 找到您想要的開源項目,分享和交流</title> 改成: <title>開源中國\s-\s找到您想要的開源項目,分享和交流</title>
測試是否能匹配經過。
很顯然,咱們匹配到了。繼續改進。
其中的中文字符以及逗號都是屬於 「非空格」,因此咱們能夠經過\S代替。繼續替換並測試。
<title>開源中國\s-\s找到您想要的開源項目,分享和交流</title> 改成: <title>\S\S\S\S\s-\s\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S</title>
依然能匹配到,貌似有些亂,容易出錯,咱們繼續改進。
語法:
* 對前一個語法進行0個或屢次匹配
+ 對前一個語法進行1次以上的匹配
{n,m} 指定次數匹配,如 \s{2,10} 即匹配2個到10個空格(區間都可)
{n} 指定次數匹配,如 \s{10} 即匹配10個空格
{n,} 指定次數匹配,如 \s{10,} 即匹配10個及10個以上空格(無上限)
此時終於能夠將那一堆\S代替了,簡直美觀。
<title>\S\S\S\S\s-\s\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S</title> 改成: <title>\S+\s-\s\S+</title> 或 <title>\S*\s-\s\S*</title> 或 <title>\S{4}\s-\s\S{16}</title>
除此以外還有方法匹配到嗎?
固然,如
<title>開源中國 - 找到您想要的開源項目,分享和交流</title> 例1: <title>[\u4e00-\u9fa5]+\s-\s[\u4e00-\u9fa5]+,[\u4e00-\u9fa5]+</title> 例2: <title>[^<]+</title>
普及下語法:
語法:
[\u4e00-\u9fa5] 中文字符 ,以及雙字節中文 [^\x00-\xff],PHP中語法爲[\x{4e00}-\x{9fa5}]
^ ‘非’邏輯符
[] 匹配的字符範圍 如[abc] ,只匹配a 或 b 或 c 這三個字符
上面第一個正則,很顯然不須要解釋,[\u4e00-\u9fa5] 這個組合是匹配中文字符的,+就是進行多個匹配。
第二個正則很簡潔,什麼意思呢。
[<] 只匹配 < (左鍵括號)
[^<] 這裏的^(非邏輯)起到的做用讓這個組合變成了,只匹配 非< ,也就是說只要不是< 均可以匹配。
[^<]+ 屢次匹配,直到將非<字符匹配完中止。
<title>[^<]+</title>
此時再看這個式子,很明顯了,將兩個title 標記中間的全部內容匹配完,也就是咱們須要的內容。
本來數據: <meta name="description" itemprop="description" content="開源中國 www.oschina.net 是目前中國最大的開源技術社區。咱們傳播開源的理念,推廣開源項目,爲 IT 開發者提供了一個發現、使用、並交流開源技術的平臺。目前開源中國社區已收錄超過兩萬款開源軟件。, 開源中國社區">
通過以上的學習,咱們能夠書寫幾個式子,如
式1: <meta name="description" itemprop="description" content="[^"]+"> 式2: <meta\s+name="description"\s+itemprop="[^"]+"\s+content="[^"]+"> 式3:(錯誤) <meta\s+name="[^"]+"\s+itemprop="[^"]+"\s+content="[^"]+">
以上3個式子,第一個第二個都很容易理解,仔細看就能看明白。
爲何第三個式子錯了呢?他不能匹配數據嗎?答案是能夠的。
在書寫正則表達式的過程當中,每每不要忘了咱們的目的,以及下降可錯性。
咱們舉例下,第三個式子可能會匹配到什麼數據?
式3: <meta\s+name="[^"]+"\s+itemprop="[^"]+"\s+content="[^"]+"> 數據1: <meta name="description" itemprop="description" content="開源中國 www.oschina.net 是目前中國最大的開源技術社區。咱們傳播開源的理念,推廣開源項目,爲 IT 開發者提供了一個發現、使用、並交流開源技術的平臺。目前開源中國社區已收錄超過兩萬款開源軟件。, 開源中國社區"> 數據2: <meta name="robots" itemprop="robots" content="index, follow"> 數據3: <meta name="viewport" itemprop="viewport" content="width=device-width, initial-scale=1">
以上三條數據,數據1是咱們的意願數據,但2和3不是,這就產生出錯了。這並非咱們所想要的。
上面的數據只是舉例測試,不是開源中國的數據。
因此在寫正則的時候,必定要有標誌性的固定字符,如上面的 name="description"
這裏都不用寫式子了,相信各位均可以很輕易的完成。
本來數據: <meta name="keywords" content="開源,OSC,開源軟件,開源硬件,開源網站,開源社區,java開源,perl開源,python開源,ruby開源,php開源,開源項目,開源代碼"> 式子: <meta\s+name="keywords"\s+content="[^"]+">
使用chrome 打開開源中國,按F12 DevTools調試,選擇Console控制檯執行JS。
js
var html = document.documentElement.outerHTML; html.match(/<title>[^<]+<\/title>/); //注意上面 <\/title> 多了一個反斜槓\ ,咱們要將正斜槓/ 轉義掉,不然影響正則表達式。 //兩邊的 /是什麼呢?這個是正則表達式的定界符,表示中間的內容爲正則主要匹配數據、模式。
結果裏面包含了title標籤,也就是固定字符,這並非咱們的預期,如何解決呢?
語法:
() 子匹配其中的內容,如 <title>([^<]+)</title>
修正代碼
html.match(/<title>([^<]+)<\/title>/); html.match(/<title>([^<]+)<\/title>/)[1];
測試以下
很簡單就取到咱們的結果。
JS的另外一種寫法:
var regular = new RegExp('<title>([^<]+)</title>'); html.match(regular);
PHP
<?php $html = file_get_contents('https://www.oschina.net/'); $pattern = '/<title>([^<]+)<\/title>/'; preg_match_all($pattern, $html,$result); echo '<pre>'; print_r($result);
JS
html.match(/<div class="box vertical news">[^<]+<a\s+class="[^"]+"\s+href="([^"]+)"[^>]+>([^<]+)<\/a>[^<]+<span\s+class="box-fr news-date">([^<]+)<\/span>\s+<\/div>/)
很不巧的是,智能匹配到1個,那麼剩下的數據爲何沒有匹配到呢?
由於match這個函數默認只返回第一次匹配的結果,不會返回全部匹配到的結果。
語法:
g 修飾符,全文匹配全部結果
修飾符用法:
/ 正則表達式 /修飾符
如: /<li[^>]+>([^<]+)<\/li>/g 全文匹配全部li
如如下便可匹配到全部的條目。
html.match(/<div class="box vertical news">[^<]+<a\s+class="[^"]+"\s+href="([^"]+)"[^>]+>([^<]+)<\/a>[^<]+<span\s+class="box-fr news-date">([^<]+)<\/span>\s+<\/div>/g);
PHP
<?php $html = file_get_contents('https://www.oschina.net/'); $pattern = '/<div class="box vertical news">[^<]+<a\s+class="[^"]+"\s+href="([^"]+)"[^>]+>([^<]+)<\/a>[^<]+<span\s+class="box-fr news-date">([^<]+)<\/span>\s+<\/div>/'; preg_match_all($pattern, $html,$result); echo '<pre>'; print_r($result);
而對於PHP而言,就不須要g了,區別於函數的選擇上。
perg_match 單次匹配
preg_match_all 全部匹配
經過以上的學習,一些簡單基本的正則匹配均可以實現。
那麼再補充說一說常規數據校驗匹配的案例,雖然網上都有。
/^\d{11}$/ 匹配11位數字(手機號)
^爲起始匹配也就說,第一個字符必須是 \d 也就是數字,$表明結束符,一樣,匹配的這段字符必須以 \d 結束才行。
/^110[0-9]{14}[0-9xX]/
/^110[0-9]{14}[0-9X]/i
匹配北京市的身份證號,110開頭,最後一位可能爲數字可能爲X。兩個式子均可以,區別於尾部x的大小寫問題,能夠寫到模式裏,能夠寫到修飾符裏。
修飾符 i 表明不區分大小寫
/[A-z_\d]+\.(jpg|png|exe)/i 文件名匹配
(jpg|png|exe) 匹配jpg 或 png 或exe ,區別於[jpg|png|exe],中括號是單個字符匹配,圓括號是總體匹配。
\. 匹配.字符,而不是任意字符,這裏被反斜槓轉義。
(.*?) 所謂的萬能正則 + 貪婪模式
. 表明任意字符
.* 表明任意字符匹配0個或者多個
.*? 表明任意字符匹配0個或者多個(最少匹配,非貪婪模式)
var string = 'aa<div>test1</div>bb<div>test2</div>cc'; string.match(/<div>.*<\/div>/); string.match(/<div>.*?<\/div>/);
能夠看到,第一個正則沒有加? 致使執行匹配到最後一個div,而增長?的只是匹配到對等的第一個div。
這個也就是正則的貪婪模式,貪婪匹配到最後一個,加上?將取消貪婪模式,也就是非貪婪模式,默認匹配到第一個就中止。
PHP中可使用修飾符 大寫U,來取消貪婪模式,如:/<div>.*<\/div>/U
模式修正符
PHP模式修飾符又叫模式修正符,是在正則表達式的定界符以外使用。主要用來調整正則表達式的解釋,提擴展了正則表達式在匹配、替換等操做的某些功能,加強了正則的能力。
模式修正符號 | 功能描述 |
---|---|
i | 在和正則匹配是不區分大小寫 |
m | 將字符串視爲多行。默認的正則開始「^」和結束「$」將目標字條串做爲一單一的一「行」字符(甚至其中包括換行符也是如此)。若是在修飾符中加上「m」,那麼開始和結束將會指點字符串的每一行的開頭就是「^」結束就是「$」。 |
s | 若是設定了這個修正符,那麼,被匹配的字符串將視爲一行來看,包括換行符,換行符將被視爲普通字符串。 |
x | 忽略空白,除非進行轉義的不被忽略。 |
e | 只用在preg_replace()函數中,在替換字符串中逆向引用作正常的替換,將其(即「替換字符串」)做爲PHP代碼求值,並用其結果來替換所搜索的字符串。 |
A | 若是使用這個修飾符,那麼表達式必須是匹配的字符串中的開頭部分。好比說」/a/A」匹配」abcd」。 |
D | 模式中的$字符權匹配目標字符的結尾。沒有此選項時,若是最後一個字符是換行符的話,美圓符號也會匹配此字符以前。若是設定了修正符m則忽略此項。 |
E | 與」m」相反,若是使用這個修飾符,那麼」$」將匹配絕對字符串的結尾,而不是換行符前面,默認就打開了這個模式。 |
U | 貪婪模式,和問號的做用差很少,最大限度的匹配就是貪婪模式。 |
[a-z] //匹配全部的小寫字母 [A-Z] //匹配全部的大寫字母 [a-zA-Z] //匹配全部的字母 [A-z] //匹配全部大小寫字母 以及 [\]^_' 這些玩意,詳查ASCII字符表。 [0-9] //匹配全部的數字 [0-9\.\-] //匹配全部的數字,句號和減號 [ \f\r\t\n] //匹配全部的白字符 \d //匹配一個數字字符。等價於 [0-9]。 \D //匹配一個非數字字符。等價於 [^0-9]。 \n //匹配一個換行符。等價於 \x0a 和 \cJ。 \r //匹配一個回車符。等價於 \x0d 和 \cM。 \s //匹配任何空白字符,包括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v]。 \S //匹配任何非空白字符。等價於 [^ \f\n\r\t\v]。 \t //匹配一個製表符。等價於 \x09 和 \cI。 \ //轉義符,若是匹配\字符,需使用 \\ 。 . //匹配除過"\n"以外的任何字符。 ? //匹配前面的子表達式零次或一次。例如,"do(es)?" 能夠匹配 "do" 或 "does" 中的"do" 。? 等價於 {0,1}。 + //匹配前面的子表達式一次或屢次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價於 {1,}。 * //匹配前面的子表達式零次或屢次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價於{0,}。 ^ //匹配輸入字符串的開始位置。若是設置了 RegExp 對象的 Multiline 屬性,^ 也匹配 '\n' 或 '\r' 以後的位置。 $ //匹配輸入字符串的結束位置。若是設置了RegExp 對象的 Multiline 屬性,$ 也匹配 '\n' 或 '\r' 以前的位置。 #修飾符 i //忽略大小寫 s //忽略換行,當作一行匹配 U //非貪婪模式
上面整理了一些簡單經常使用的,元字符以及模式規則,這些東西能夠不用一次記住,書寫的時候隨時來查閱參考便可,寫的多了,天然就會掌握這些規則技巧,徹底不用刻意記。
本文引用: