瑞士軍刀---正則表達式

簡介

正則表達式,又稱正規表示法、正規表達式、規則表達式、常規表示法(英語:Regular Expression,在代碼中常簡寫爲regex、regexp或RE),計算機科學的一個概念。正則表達式使用單個字符串來描述、匹配一系列符合某個句法規則的字符串。在不少文本編輯器裏,正則表達式一般被用來檢索、替換那些符合某個模式的文本。javascript

說人話就是:對字符串執行模式匹配的強大工具。前端

Javascript中的正則表達式相較於其餘語言來講實現的並不完整,但仍然是十分強大的,可以幫助咱們完成絕大多數模式匹配任務。java

定義

在javascript中,正則表達式的定義和數組以及對象的定義同樣有倆種方式。 一種是直接量,另外一種是構造函數。node

直接量

Javascript可使用相似Perl的語法定義一個正則表達式正則表達式

var r = /pattern/flags;

其中pattern是任何簡單或複雜的正則表達式,flags是用以表達正則表達式行爲的一個或者多個標識。數組

flags編輯器

  • g 表示全局(global)模式,即模式將被應用於全部字符串函數

  • i 表示不區分大小寫工具

  • m 多行模式編碼

舉個栗子:

var reg1 = /ip/g; // 匹配字符串中全部'ip'的實例

var reg2 = /com/gi; // 匹配以'com'結尾的三個字符的組合,不區分大小寫

使用構造函數

Javascript中正則表達式的構造函數爲RegExp,即Regular Expression的縮寫,它接收兩個參數,第一個爲要匹配的字符串模式,另外一個是可選的標識位。

var reg = new RegExp('nice', 'g'); // 匹配字符串中全部的'nice'

注意:第一個參數是一個字符串nice,而不是正則表達式的直接量/nice/

雙重轉義

全部元字符都須要進行雙重轉義

全部元字符都須要進行雙重轉義

全部元字符都須要進行雙重轉義

使用構造函數定義正則表達式,因爲構造函數的第一個參數必須是一個字符串,在匹配元字符時,須要雙重轉義。

//  匹配{user}
var reg1 = new RegExp('\{user\}', 'g'); // wrong

// 因爲\在字符串中須要轉義爲\\,因此,若是要匹配{user},正則表達式須要寫爲
var reg1 = new RegExp('\\{user\\}', 'g');

基本概念總結

元字符

在正則表達式的模式中,有一些字符是有特殊含義的,被稱爲元字符,若是要匹配元字符,則必須對其進行轉義,若是用構造函數,則要進行雙重轉義。

這些元字符分別是(一共14個):

{ ( [  \ ^ $ |  ? * + . ] ) }

直接量字符

| 字符 | 匹配 |
| ------------- |:-------------:|
|字母數字字符|自身|
|\0 |查找 NUL 字符。|
|\n |查找換行符。|
|\f |查找換頁符。|
|\r |查找回車符。|
|\t |查找製表符。|
|\v |查找垂直製表符。|
|\xxx |查找以八進制數 xxx 規定的字符。|
|\xdd |查找以十六進制數 dd 規定的字符。|
|\uxxxx |查找以十六進制數 xxxx 規定的 Unicode 字符。|

無論一個直接量字符字符表明何種含義,單個字符始終只匹配單個字符

字符類

| 字符 |等價於| 匹配 |
| ------------- |:-------------:| :-------------:|
| . | 1|查找單個字符,除了換行和行結束符。 |
| \w| [a-zA-Z_0-9]|任意ASCII單字字符,等價於[a-zA-Z0-9_]|
| \W| 2 |查找非單詞字符。 |
|\d |[0-9]|查找數字。|
|\D |3|查找非數字字符。|
|\s |[ \t\n\x0B\f\r]|查找空白字符。|
|\S |4|查找非空白字符。|
|[]||來表示單個字符有或的關係,如/[bc]/,匹配b或者c|
|^||來表示不匹配後面跟着的字符,如/5,/不匹配b或c|
|-||來表示一個範圍,如/[a-z]/,匹配a-z的字母,能夠和負向類結合/^0-9/|
|組合類:||以上幾種類組合而成的字符類,如/a-z0-9\n/,匹配a-z的字母或者0-9的數字或者換行符|

注意:在javascript類不能嵌套,就是不支持聯合類和交叉類,/a-m[p-z]/和/a-m6/在JavaScript中是非法的

錨字符

| 字符 | 含義|
| ------------- |:-------------:|
| ^ | 匹配字符串的開頭,在多行檢索中,匹配一行的開頭|
| $| 匹配字符串的結尾,在多行檢索中,匹配一行的結尾|
|\b |匹配單詞邊界。|
|\B |匹配非單詞邊界。|

量詞

簡單量詞

| 經常使用量詞 | {m,n}等價形式|描述 |
| ------------- |:-------------:| :-------------:|
|?|{0,1}|最多出現1次,例如,do(es)? 匹配 do 或 does 中的 do|
|* |{0,}|可能出現,也可能不出現,出現次數無上限,例如,zo* 匹配 z 和 zoo。|
|+ |{1,}|最少出現1次,例如,zo+ 匹配 zo 和 zoo,但不匹配 z|

在正則表達式概念中,稱 +、*、?爲經常使用量詞,稱{n,m}形式的爲通用量詞。

使用情景舉例

**?的使用
**
情景:美式應用和英式語言的單詞寫法不一樣,好比traveler和traveller.

var str1 = 'traveler';
var str2 = 'traveller';
var pattern = /travell?er/;
console.log(pattern.test(str1));
console.log(str2.search(str2));

結果打印:
true
0

匹配各種標籤(前端應用)

  • 匹配因此tag: /<7+>/

  • 匹配open tag: /<87*>/

  • 匹配close tag: /</7+>/

  • 匹配self-closing tag: /9+/>/

複雜量詞

  • 貪婪量詞:先匹配整個字符串,若是不匹配則去掉最後一個字符再匹配,直到沒有任何字符。它是從後向前匹配。全部簡單量詞都是貪婪的

  • 惰性量詞:和貪婪量詞相反,即先匹配第一個字符,不匹配則匹配第一第二個字符,直到最後整個字符串。全部簡單量詞後面加?就是惰性的了

  • 支配量詞:只匹配整個字符串一次,不匹配就結束,也稱最懶量詞,全部簡單量詞後面加+就是支配的了,可是javascript不支持,因此它連出場的機會也沒有了。

舉個栗子(complex-quantifiers.js):

var re1 = /.*bbb/g;        //  定義貪婪量詞
var re2 = /.*?bbb/g;    //  定義簡單惰性
//  var re3 = /.*+bbb/g;//支配性,javascript不支持,nodejs報錯
var  str='abbbaabbbaaabbb1234';

console.log(re1.test(str));  //true
console.log(re1.exec(str));  //null
console.log(str.match(re1));  //abbbaabbbaaabbbb

console.log(re2.test(str));  //true
console.log(re2.exec(str));  //aabbb
console.log(str.match(re2)); //abbb,aabbb,aaabbb

貪婪模式詳解

分組

到目前爲止,咱們只能一個字符到匹配,雖然量詞的出現,能幫助咱們處理一排密緊密相連的同類型字符。但這是不夠的,下面該輪到小括號出場了,中括號表示範圍內選擇,大括號表示重複次數。小括號容許咱們重複多個字符。

舉個栗子(group.js):

//分組+量詞
console.log(/(dog){2}/.test("dogdog"))//true
//分組+範圍
console.log("baddad".match(/([bd]ad?)*/))//baddad,dad
//分組+分組
console.log("mon and dad".match(/(mon( and dad)?)/))//mon and dad,mon and dad, and dad

優先級

|優先級| 符號|說明|
| ------------- |:-------------:| :-------------:|
|最高 |\|轉義符|
|高 |( )、(?: )、(?= )、[ ]|單元和字符類|
|中 |*、+、?、{n}、{n,}、{m,n}|量詞|
|低 |^、$、\任何元字符、任何字符|描點|
|最低|\||替換,選擇|

參考加減乘除,先算括號內的記憶方式

RegExp對象

RegExp屬性

global 屬性 | ignoreCase 屬性 | multiline 屬性 | source 屬性

  • global: 返回布爾值,該值指示使用正則表達式的 global 標誌 (g) 的狀態。 默認值爲 false。 只讀。

  • ignoreCase: 返回布爾值,該值指示在正則表達式中使用的 ignoreCase 標誌 (i) 的狀態。 默認值爲 false。 只讀。

  • multiline: 返回布爾值,該值指示在正則表達式中使用的 multiline 標誌 (m) 的狀態。 默認值爲 false。 只讀。

  • source: 返回正則表達式模式的文本的一個副本。 只讀。

  • lastIndex: 若是使用了全局模式,這個變量保存的是字符串中嘗試下次匹配的偏移值。在exec和test中都會用到這個變量。 可寫

RegExp方法

RegExp 對象有 3 個方法:test()、exec() 以及 compile()

RegExp.test(string)

test 方法檢查字符串中是否存在某種模式,若是存在,則返回 true,不然返回 false。test 方法不修改全局 RegExp 對象的屬性。

語法:

rgExp.test(str) 

//  參數
rgExp 必需。 包含正則表達式模式和適用標誌的 Regular Expression 對象的實例。
str 必需。 將對其執行搜索的字符串。

栗子:

var str = 'huangge is an handsome man';

var reg1 = new RegExp( 'handsome', 'g' );
var result = reg1.test(str);
console.log('huangge is an handsome man: ' + result);
RegExp.exec(string)

exec 方法使用正則表達式模式對字符串執行需找匹配,若是成功,則返回表示匹配信息的數組,不然返回null。默認狀況下,它返回第一次匹配的結果

語法:

rgExp.exec(str) 

//  參數
rgExp 必需。 包含正則表達式模式和適用標誌的 Regular Expression 對象的實例。
str 必需。 對其執行搜索的 String 對象或字符串文本。

返回值

若是成功匹配,exec 方法返回一個數組,而且更新正則表達式對象的屬性。返回的數組包括匹配的字符串做爲第一個元素,緊接着一個元素對應一個成功匹配被捕獲的字符串的捕獲括號(capturing parenthesis)。

若是匹配失敗,exec 方法將返回 null。

栗子(regexp-exec.js):

var reg= /\d{4}-\d{2}-\d{2}/g;
var str = 'aaa2015-08-11aaaaaabbss2015-08-22bbb';
var result = reg.exec(str);
console.log(result);


結果以下:

[ '2015-08-11',
  index: 3,
  input: 'aaa2015-08-11aaaaaabbss2015-08-22bbb' ]
RegExp.compile(string)

將正則表達式編譯爲內部格式,從而更快地執行。

語法:

rgExp.compile(pattern, [flags]) 

//  參數
rgExp 必需。 Regular Expression 對象的一個實例。 能夠是變量名或文本。
pattern 必需。 一個字符串表達式,包含要編譯的正則表達式模式
flags 可選。 能夠組合使用的可用標誌有:
    g(全局搜索出現的全部模式)
    i(忽略大小寫)
    m(多行搜索)

compile 方法將 pattern 轉換爲內部的格式,從而執行得更快。 例如,這容許在循環中更有效地使用正則表達式。 當重複使用相同的表達式時,編譯過的正則表達式使執行加速。 然而,若是正則表達式發生更改,則這種編譯毫無益處。

String的正則方法

String.match(RegExp)

這個方法相似RegExp.exec(string),只是調換了RegExp和string的位置。 另外一個區別就是,不管是否指定全局,RegExp.exec(string)只是返回單詞匹配結果。 而string.match()會返回一個字符串數組,其中包含了各次匹配成功的文本

舉個栗子(string-match.js):

var reg= /\d{4}-\d{2}-\d{2}/g;
var str = 'aaa2015-08-11aaaaaabbss2015-08-22bbb';
var result = str.match(reg);
console.log(result);

打印的結果爲:

[ '2015-08-11', '2015-08-22' ]
String.search(RegEexp)

這個用來尋找某個正則表達式在字符串第一次匹配成功的位置,若是不成功,則返回-1

舉個栗子(string-search.js):

var str1 = 'sssssaa111';
var str2 = 'sssssaaaaa';

var pattern = /\d/;
console.log ('st1  ' + str1.search(pattern));
console.log ('st2  ' + str2.search(pattern));

打印的結果爲:

st1  7
st2  -1
String.replace(RegExp,replacement)

這個方法用來正則表達式替換。 將匹配到的文本替換爲replacement。默認狀況替換一次。若是設定了全局模式,則全部能匹配的文本都會替換。
舉個栗子(string-replace.js):

var reg = /\d{4}-\d{2}-\d{2}/;
var str = '2015-08-11 2015-08-22';

console.log(str.replace(reg, 'Date:'));

打印的結果爲:

ate: 2015-08-22
String.split(RegExp [,limit])

這個方法使用一個正則表達式切分字符串,正則表達式是否使用全局對結果沒有影響
舉個栗子(string-split.js):

var str = 'one two  three    four';
var pattern = /\s+/;
console.log(str.split(pattern))

打印的結果爲:

[ 'one', 'two', 'three', 'four' ]

經常使用的正則表達式

  • 匹配中文字符的正則表達式: [\u4e00-\u9fa5]

  • 匹配雙字節字符(包括漢字在內):10
    評註:能夠用來計算字符串的長度(一個雙字節字符長度計2,ASCII字符計1)

  • 匹配空白行的正則表達式:\n\s*\r

  • 匹配HTML標記的正則表達式:<(\S?)7>.?</\1>|<.? />

  • 匹配首尾空白字符的正則表達式:^\s|\s$

  • 匹配Email地址的正則表達式:\w+([-+.]\w+)@\w+([-.]\w+)\.\w+([-.]\w+)*

  • 匹配網址URL的正則表達式:[a-zA-z]+://11*

  • 匹配賬號是否合法(字母開頭,容許5-16字節,容許字母數字下劃線):^a-zA-Z{4,15}$

  • 匹配國內電話號碼:\d{3}-\d{8}|\d{4}-\d{7}

  • 匹配騰訊QQ號:1-9{4,}

  • 匹配中國郵政編碼:[1-9]\d{5}(?!\d)

  • 匹配身份證:\d{15}|\d{18}

  • 匹配ip地址:\d+\.\d+\.\d+\.\d+

匹配特定數字

^[1-9]\d*$    //匹配正整數
^-[1-9]\d*$   //匹配負整數
^-?[1-9]\d*$   //匹配整數
^[1-9]\d*|0$  //匹配非負整數(正整數 + 0)
^-[1-9]\d*|0$   //匹配非正整數(負整數 + 0)
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$   //匹配正浮點數
^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$  //匹配負浮點數
^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$  //匹配浮點數
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$   //匹配非負浮點數(正浮點數 + 0)
^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$  //匹配非正浮點數(負浮點數 + 0)

匹配特定字符串

^[A-Za-z]+$  //匹配由26個英文字母組成的字符串
^[A-Z]+$  //匹配由26個英文字母的大寫組成的字符串
^[a-z]+$  //匹配由26個英文字母的小寫組成的字符串
^[A-Za-z0-9]+$  //匹配由數字和26個英文字母組成的字符串
^\w+$  //匹配由數字、26個英文字母或者下劃線組成的字符串

  1. \n\r
  2. a-zA-Z_0-9
  3. 0-9
  4. \t\n\x0B\f\r
  5. bc
  6. b-e
  7. >
  8. />
  9. >/
  10. \x00-\xff
  11. \s
相關文章
相關標籤/搜索