javascript中正則表達式的基礎語法

前面的話

  正則表達式在人們的印象中多是一堆沒法理解的字符,但就是這些符號卻實現了字符串的高效操做。一般的狀況是,問題自己並不複雜,但沒有正則表達式就成了大問題。javascript中的正則表達式做爲至關重要的知識,本文將介紹正則表達式的基礎語法javascript

 

定義

  正則表達式(Regular Expression)是一門簡單語言的語法規範,是強大、便捷、高效的文本處理工具,它應用在一些方法中,對字符串中的信息實現查找、替換和提取操做html

  javascript中的正則表達式用RegExp對象表示,有兩種寫法:一種是字面量寫法;另外一種是構造函數寫法java

Perl寫法git

  正則表達式字面量寫法,又叫Perl寫法,由於javascript的正則表達式特性借鑑自Perl正則表達式

  正則表達式字面量定義爲包含在一對斜槓(/)之間的字符,而且能夠設置3個標誌express

var expression = /pattern/flags;

  正則表達式的匹配模式支持下列3個標誌:數組

  g:表示全局(global)模式,即模式將被應用於全部字符串,而並不是在發現第一個匹配項時當即中止app

  i:表示不區分大小寫(case-insensitive)模式,即在肯定匹配項時忽略模式與字符串的大小寫函數

  m:表示多行(multiline)模式,即在到達一行文本末尾時還會繼續查找下一行中是否存在與模式匹配的項工具

//匹配字符串全部'at'的實例
var p = /at/g;
//test()方法返回一個布爾值表示是否能夠找到匹配項
console.log(p.test('ata'));//true
console.log(p.test('aba'));//false

RegExp構造函數

  和普通的內置對象同樣,RegExp正則表達式對象也支持new RegExp()構造函數的形式

  RegExp構造函數接收兩個參數:要匹配的字符串模式(pattern)和可選的標誌字符串(flags),標誌字符串和字面量的三個標誌含義相同:'g'、'i'、'm'

  RegExp構造函數的兩個參數都是字符串。且使用字面量形式定義的任何表達式均可使用構造函數

//匹配字符串全部'at'的實例
var p1 = /at/g;
//同上
var p2 = new RegExp('at','g');

  [注意]ES3規範規定,一個正則表達式直接量會在執行到它時轉換爲一個RegExp對象,同一段代碼所表示正則表達式直接量的每次運算都返回同一個對象。ES5規範則作了相反的規定,同一段代碼所表示的正則表達式直接量的每次運算都返回新對象。IE6-8一直是按照ECMAScript5規範的方式實現的,因此並無兼容性問題

 

特色

  javascript中的正則表達式最大的特色是不支持空白,必須寫在一行中

//匹配ab
console.log(/ab/.test('ab')); //true
console.log(/ ab/.test('ab')); //false
console.log(/a b/.test('ab')); //false
console.log(/ab /.test('ab')); //false

 

元字符

  大部分字符在正則表達式中,就是字面的含義,好比/a/匹配a,/b/匹配b

/dog/.test("old dog") // true

  但還有一些字符,它們除了字面意思外,還有着特殊的含義,這些字符就是元字符

  在javascript中,共有14個元字符(meta-character)

() [] {} \ ^ $ | ? * + . 
元字符         名稱              匹配對象
.             點號               單個任意字符(除回車\r、換行\n、行分隔符\u2028和段分隔符\u2029外)
[]            字符組             列出的單個任意字符
[^]           排除型字符組        未列出的單個任意字符
?             問號               匹配0次或1次
*             星號               匹配0交或屢次
+             加號               匹配1次或屢次
{min,max}     區間量詞            匹配至少min次,最多max次
^             脫字符             行的起始位置
$             美圓符             行的結束位置
|             豎線               分隔兩邊的任意一個表達式
()            括號               限制多選結構的範圍,標註量詞做用的元素,爲反向引用捕獲文本
\1,\2...      反向引用            匹配以前的第1、第二...組括號內的表達式匹配的文本

 

轉義字符

  轉義字符(escape)表示爲反斜線(\)+字符的形式,共有如下3種狀況

  【1】由於元字符有特殊的含義,因此沒法直接匹配。若是要匹配它們自己,則須要在它們前面加上反斜槓(\)

console.log(/1+1/.test('1+1')); //false
console.log(/1\+1/.test('1+1')); //true

console.log(/\*/.test('*')); //true
console.log(/*/.test('*')); //報錯

  但實際上,並不是14個元字符都須要轉義,右方括號]和右花括號}不須要轉義

console.log(/]/.test(']')); //true
console.log(/\]/.test(']')); //true

console.log(/\}/.test('}')); //true
console.log(/}/.test('}')); //true

  【2】'\'加非元字符,表示一些不能打印的特殊字符

\0        NUL字符\u0000
[\b]      匹配退格符\u0008,不要與\b混淆
\t        製表符\u0009
\n        換行符\u000A
\v        垂直製表符\u000B
\f        換頁符\u000C
\r        回車符\u000D
\xnn      由十六進制數nn指定的拉丁字符
\uxxxx    由十六進制數xxxx指定的Unicode字符(\u4e00-\u9fa5表明中文)  
\cX       控制字符^X,表示ctrl-[X],其中的X是A-Z之中任一個英文字母,用來匹配控制字符

  【3】'\'加任意其餘字符,默認狀況就是匹配此字符,也就是說,反斜線(\)被忽略了

console.log(/\x/.test('x')); //true
console.log(/\y/.test('y')); //true
console.log(/\z/.test('z')); //true

雙重轉義

  因爲RegExp構造函數的參數是字符串,因此某些狀況下,須要對字符進行雙重轉義

  字符\在正則表達式字符串中一般被轉義爲\\

var p1 = /\.at/;
//等價於
var p2 = new RegExp('\\.at');

var p1 = /name\/age/;
//等價於
var p2 = new RegExp('name\\/age');

var p1 = /\w\\hello\\123/;
//等價於
var p2 = new RegExp('\\w\\\\hello\\\\123');

 

字符組

  字符組(Character Class),有的編譯成字符類或字符集。簡單而言,就是指用方括號表示的一組字符,它匹配若干字符之一

//匹配0-9這10個數字之一
var p = /[0123456789]/;
p.test('1');//true
p.test('a');//false

  [注意]字符組中的字符排列順序並不影響字符組的功能,出現重複字符也不會影響

/[0123456789]/
//等價於
/[9876543210]/
//等價於
/[1234567890123456789]/

範圍

  正則表達式經過連字符(-)提供了範圍表示法,能夠簡化字符組

/[0123456789]/
//等價於
/[0-9]/
/[abcdefghijklmnopqrstuvwxyz]/
//等價於
/[a-z]/

  連字符(-)表示的範圍是根據ASCII編碼的碼值來肯定的,碼值小的在前,碼值大的在後

  因此[0-9]是合法的,而[9-0]會報錯

//匹配0-9這10個數字之一
var p1 = /[0-9]/;
p1.test('1');//true
var p2 = /[9-0]/;//報錯
p2.test('1');

  在字符組中能夠同時並列多個'-'範圍

/[0-9a-zA-Z]/;//匹配數字、大寫字母和小寫字母
/[0-9a-fA-F]/;//匹配數字,大、小寫形式的a-f,用來驗證十六進制字符

console.log(/[0-9a-fA-F]/.test('d'));//true
console.log(/[0-9a-fA-F]/.test('x'));//false

  只有在字符組內部,連字符'-'纔是元字符,表示一個範圍,不然它就只能匹配普通的連字符號

  [注意]若是連字符出如今字符組的開頭或末尾,它表示的也是普通的連字符號,而不是一個範圍

//匹配中劃線
console.log(/-/.test('-'));//true
console.log(/[-]/.test('-'));//true

//匹配0-9的數字或中劃線
console.log(/[0-9]/.test('-'));//false
console.log(/[0-9-]/.test('-'));//true
console.log(/[0-9\-]/.test('-'));//true
console.log(/[-0-9]/.test('-'));//true
console.log(/[\-0-9]/.test('-'));//true

排除

  字符組的另外一個類型是排除型字符組,在左方括號後緊跟一個脫字符'^'表示,表示在當前位置匹配一個沒有列出的字符 

  因此[^0-9]表示0-9之外的字符

//匹配第一個是數字字符,第二個不是數字字符的字符串
console.log(/[0-9][^0-9]/.test('1e'));//true
console.log(/[0-9][^0-9]/.test('q2'));//false

  [注意]在字符組內部,脫字符'^'表示排除,而在字符組外部,脫字符'^'表示一個行錨點

  ^符號是元字符,在字符組中只要^符號不挨着左方括號就能夠表示其自己含義,不轉義也能夠

//匹配abc和^符號
console.log(/[a-c^]/.test('^'));//true
console.log(/[a-c\^]/.test('^'));//true
console.log(/[\^a-c]/.test('^'));//true

  在字符組中,只有^、-、[、]這4個字符可能被當作元字符,其餘有元字符功能的字符都只表示其自己

console.log(/[[1]]/.test('['));//false
console.log(/[[1]]/.test(']'));//false
console.log(/[\1]/.test('\\'));//false
console.log(/[^^]/.test('^'));//false
console.log(/[1-2]/.test('-'));//false

console.log(/[\[1\]]/.test('['));//true
console.log(/[\[1\]]/.test(']'));//true
console.log(/[\\]/.test('\\'));//true
console.log(/[^]/.test('^'));//true
console.log(/[1-2\-]/.test('-'));//true
console.log(/[(1)]/.test('('));//true
console.log(/[(1)]/.test(')'));//true
console.log(/[{1}]/.test('{'));//true
console.log(/[{1}]/.test('}'));//true
console.log(/[1$]/.test('$'));//true
console.log(/[1|2]/.test('|'));//true
console.log(/[1?]/.test('?'));//true
console.log(/[1*]/.test('*'));//true
console.log(/[1+]/.test('+'));//true
console.log(/[1.]/.test('.'));//true

簡記

  用[0-9]、[a-z]等字符組,能夠很方便地表示數字字符和小寫字母字符。對於這類經常使用字符組,正則表達式提供了更簡單的記法,這就是字符組簡記(shorthands)

  常見的字符組簡記有\d、\w、\s。其中d表示(digit)數字,w表示(word)單詞,s表示(space)空白

  正則表達式也提供了對應排除型字符組的簡記法:\D、\W、\S。字母徹底相同,只是改成大寫,這些簡記法匹配的字符互補

\d     數字,等同於[0-9]
\D     非數字,等同於[^0-9]
\s     空白字符,等同於[\f\n\r\t\u000B\u0020\u00A0\u2028\u2029]
\S     非空白字符,等同於[^\f\n\r\t\u000B\u0020\u00A0\u2028\u2029]
\w     字母、數字、下劃線,等同於[0-9A-Za-z_](漢字不屬於\w)
\W     非字母、數字、下劃線,等同於[^0-9A-Za-z_]

  [注意]\w不只包括字母、數字,還包括下劃線。在進行數字驗證時,只容許輸入字母和數字時,不可使用\w,而應該使用[0-9a-zA-Z]

任意字符

  人們通常認爲點號能夠表明任意字符,其實並非

  .點號表明除回車(\r)、換行(\n) 、行分隔符(\u2028)和段分隔符(\u2029)之外的任意字符

  妥善的利用互補屬性,能夠獲得一些巧妙的效果。好比,[\s\S]、[\w\W]、[\d\D]均可以表示任意字符

//匹配任意字符
console.log(/./.test('\r'));//false
console.log(/[\s\S]/.test('\r'));//true

 

量詞

  根據字符組的介紹,能夠用字符組[0-9]或\d來匹配單個數字字符,若是用正則表達式表示更復雜的字符串,則不太方便

//表示郵政編碼6位數字
/[0-9][0-9][0-9][0-9][0-9][0-9]/;
//等價於
/\d\d\d\d\d\d/;

  正則表達式提供了量詞,用來設定某個模式出現的次數

{n}       匹配n次
{n,m}     匹配至少n次,最多m次
{n,}      匹配至少n次
?         至關於{0,1}
*         至關於{0,}
+         至關於{1,}
//表示郵政編碼6位數字
/\d{6}/;

  美國英語和英國英語有些詞的寫法不同,若是traveler和traveller,favor和favour,color和colour

//同時匹配美國英語和英國英語單詞
/travell?er/;
/favou?r/;
/colou?r/;

  協議名有http和https兩種

/https?/;

  量詞普遍應用於解析HTML代碼。HTML是一種標籤語言,它包含各類各樣的標籤,好比<head>、<img>、<table>。它們都是從<開始,到>結束,而標籤名的長度不一樣

console.log(/<[^<>]+>/.test('<head>'));//true
console.log(/<[^<>]+>/.test('<img>'));//true
console.log(/<[^<>]+>/.test('<>'));//false

  HTML標籤不能爲空標籤,而引號字符串的兩個引號之間能夠爲0個字符

console.log(/'[^']*'/.test("''"));//true
console.log(/'[^']*'/.test("'abc'"));//true

貪婪模式

  默認狀況下,量詞都是貪婪模式(greedy quantifier),即匹配到下一個字符不知足匹配規則爲止

//exec()方法以數組的形式返回匹配結果
/a+/.exec('aaa'); // ['aaa']

懶惰模式

  懶惰模式(lazy quantifier)和貪婪模式相對應,在量詞後加問號'?'表示,表示儘量少的匹配,一旦條件知足就再不往下匹配

{n}?       匹配n次
{n,m}?     匹配至少n次,最多m次
{n,}?      匹配至少n次
??         至關於{0,1}
*?         至關於{0,}
+?         至關於{1,}
/a+?/.exec('aaa'); // ['a']

  匹配<script></script>之間的代碼看上去很容易

/<script>[\s\S]*<\/script>/
//["<script>alert("1");</script>"]
/<script>[\s\S]*<\/script>/.exec('<script>alert("1");</script>'); 

  但若是屢次出現script標籤,就會出問題

//["<script>alert("1");</script><br><script>alert("2");</script>"]
/<script>[\s\S]*<\/script>/.exec('<script>alert("1");</script><br><script>alert("2");</script>');     

  它把無用的<br>標籤也匹配出來了,此時就須要使用懶惰模式

//["<script>alert("1");</script>"]
/<script>[\s\S]*?<\/script>/.exec('<script>alert("1");</script><br><script>alert("2");</script>');     

  在javascript中,/* */是註釋的一種形式,在文檔中可能出現屢次,這時就必須使用懶惰模式

/\/\*[\s\S]*?\*\//
//["/*abc*/"]
/\/\*[\s\S]*?\*\//.exec('/*abc*/<br>/*123*/');

 

括號

  括號有兩個功能,分別是分組和引用。具體而言,用於限定量詞或選擇項的做用範圍,也能夠用於捕獲文本並進行引用或反向引用

分組

  量詞控制以前元素的出現次數,而這個元素多是一個字符,也多是一個字符組,也能夠是一個表達式

  若是把一個表達式用括號包圍起來,這個元素就是括號裏的表達式,被稱爲子表達式

  若是但願字符串'ab'重複出現2次,應該寫爲(ab){2},而若是寫爲ab{2},則{2}只限定b

console.log(/(ab){2}/.test('abab'));//true
console.log(/(ab){2}/.test('abb'));//false
console.log(/ab{2}/.test('abab'));//false
console.log(/ab{2}/.test('abb'));//true

  身份證長度有15位和18位兩種,若是隻匹配長度,可能會想固然地寫成\d{15,18},實際上這是錯誤的,由於它包括1五、1六、1七、18這四種長度。所以,正確的寫法應該是\d{15}(\d{3})?

  email地址以@分隔成兩段,以前的部分是用戶名,以後的部分是主機名

  用戶名容許出現數字、字母和下劃線,長度通常在1-64個字符之間,則正則可表示爲/\w{1,64}/

  主機名通常表現爲a.b.···.c,其中c爲主域名,其餘爲級數不定的子域名,則正則可表示爲/([-a-zA-z0-9]{1,63}\.)+[-a-zA-Z0-9]{1,63}/

  因此email地址的正則表達式以下:

    var p =/\w{1,64}@([-a-zA-z0-9]{1,63}\.)+[-a-zA-Z0-9]{1,63}/;
    console.log(p.test('q@qq.com'));//true
    console.log(p.test('q@qq'));//false
    console.log(p.test('q@a.qq.com'));//true

捕獲

  括號不只能夠對元素進行分組,還會保存每一個分組匹配的文本,等到匹配完成後,引用捕獲的內容。由於捕獲了文本,這種功能叫捕獲分組

  好比,要匹配諸如2016-06-23這樣的日期字符串

/(\d{4})-(\d{2})-(\d{2})/

  與以往不一樣的是,年、月、日這三個數值被括號括起來了,從左到右爲第1個括號、第2個括號和第3個括號,分別表明第一、二、3個捕獲組

  javascript有9個用於存儲捕獲組的構造函數屬性

RegExp.$1\RegExp.$2\RegExp.$3……到RegExp.$9分別用於存儲第1、第二……第九個匹配的捕獲組。在調用exec()或test()方法時,這些屬性會被自動填充
console.log(/(\d{4})-(\d{2})-(\d{2})/.test('2016-06-23'));//true
console.log(RegExp.$1);//'2016'
console.log(RegExp.$2);//'06'
console.log(RegExp.$3);//'23'
console.log(RegExp.$4);//''

  而exec()方法是專門爲捕獲組而設計的,返回的數組中,第一項是與整個模式匹配的字符串,其餘項是與模式中的捕獲組匹配的字符串

console.log(/(\d{4})-(\d{2})-(\d{2})/.exec('2016-06-23'));//["2016-06-23", "2016", "06", "23"]

  捕獲分組捕獲的文本,不只能夠用於數據提取,也能夠用於替換

  replace()方法就是用於進行數據替換的,該方法接收兩個參數,第一個參數爲待查找的內容,而第二個參數爲替換的內容

console.log('2000-01-01'.replace(/-/g,'.'));//2000.01.01

  在replace()方法中也能夠引用分組,形式是$num,num是對應分組的編號

//把2000-01-01的形式變成01-01-2000的形式
console.log('2000-01-01'.replace(/(\d{4})-(\d{2})-(\d{2})/g,'$3-$2-$1'));//'01-01-2000'

反向引用

  英文中很多單詞都有重疊出現的字母,如shoot或beep。若想檢查某個單詞是否包含重疊出現的字母,則須要引入反向引用(back-reference)

  反向引用容許在正則表達式內部引用以前捕獲分組匹配的文本,形式是\num,num表示所引用分組的編號

//重複字母
/([a-z])\1/
console.log(/([a-z])\1/.test('aa'));//true
console.log(/([a-z])\1/.test('ab'));//false

  反向引用能夠用於創建先後聯繫。HTML標籤的開始標籤和結束標籤是對應的

//開始標籤
<([^>]+)>
//標籤內容
[\s\S]*?
//匹配成對的標籤
/<([^>]+)>[\s\S]*?<\/\1>/

console.log(/<([^>]+)>[\s\S]*?<\/\1>/.test('<a>123</a>'));//true
console.log(/<([^>]+)>[\s\S]*?<\/\1>/.test('<a>123</b>'));//false

非捕獲

  除了捕獲分組,正則表達式還提供了非捕獲分組(non-capturing group),以(?:)的形式表示,它只用於限定做用範圍,而不捕獲任何文本

  好比,要匹配abcabc這個字符,通常地,能夠寫爲(abc){2},但因爲並不須要捕獲文本,只是限定了量詞的做用範圍,因此應該寫爲(?:abc){2}

console.log(/(abc){2}/.test('abcabc'));//true
console.log(/(?:abc){2}/.test('abcabc'));//true

  因爲非捕獲分組不捕獲文本,對應地,也就沒有捕獲組編號

console.log(/(abc){2}/.test('abcabc'));//true
console.log(RegExp.$1);//'abc'
console.log(/(?:abc){2}/.test('abcabc'));//true
console.log(RegExp.$1);//''

  非捕獲分組也不可使用反向引用

/(?:123)\1/.test('123123');//false
/(123)\1/.test('123123');//true

  捕獲分組和非捕獲分組能夠在一個正則表達式中同時出現

console.log(/(\d)(\d)(?:\d)(\d)(\d)/.exec('12345'));//["12345", "1", "2", "4", "5"]

 

選擇

  豎線'|'在正則表達式中表示(OR)關係的選擇,以豎線'|'分隔開的多個子表達式也叫選擇分支或選擇項。在一個選擇結構中,選擇分支的數目沒有限制

  在選擇結構中,豎線|用來分隔選擇項,而括號()用來規定整個選擇結構的範圍。若是沒有出現括號,則將整個表達式視爲一個選擇結構

  選擇項的嘗試匹配次序是從左到右,直到發現了匹配項,若是某個選擇項匹配就忽略右側其餘選擇項,若是全部子選擇項都不匹配,則整個選擇結構匹配失敗

console.log(/12|23|34/.exec('1'));//null
console.log(/12|23|34/.exec('12'));//['12']
console.log(/12|23|34/.exec('23'));//['23']
console.log(/12|23|34/.exec('2334'));//['23']

  ip地址通常由3個點號和4段數字組成,每段數字都在0-255之間

(00)?\d; //0-9
0?[1-9]\d;//10-99
1\d{2};//100-199
2[0-4]\d;//200-249
25[0-5];//250-255
//數字(0-255)
/(00)?\d|0?[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]/;
//ip地址
var ip = /^(((00)?\d|0?[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}\2$/;
console.log(ip.test('1.1.1.1'));//true
console.log(ip.test('1.1.1'));//false
console.log(ip.test('256.1.1.1'));//false

  相似地,時間匹配也須要分段處理

//月(1-12)
0?\d|1[0-2]
//日(1-31)
0?\d|[12]\d|3[01]
//小時(0-24)
0?\d|1\d|2[0-4]
//分鐘(0-60)
0?\d|[1-5]\d|60

  手機號通常是11位,前3位是號段,後8位通常沒有限制。並且,在手機開頭極可能有0或+86

//開頭
(0|\+86)?
//前3位
13\d|14[579]|15[0-35-9]|17[0135-8]|18\d
//後8位
\d{8}

//手機號碼
var phone = /(0|\+86)?(13\d|14[579]|15[0-35-9]|17[0135-8]|18\d)\d{8}/;
console.log(phone.test('13453250661'));//true
console.log(phone.test('1913250661'));//false
console.log(phone.test('1345325061'));//false

  在選擇結構中,應該儘可能避免選擇分支中存在重複匹配,由於這樣會大大增長回溯的計算量

//不良的選擇結構
a|[ab]
[0-9]|\w

 

斷言

  在正則表達式中,有些結構並不真正匹配文本,而只負責判斷在某個位置左/右側是否符合要求,這種結構被稱爲斷言(assertion),也稱爲錨點(anchor),常見的斷言有3種:單詞邊界、行開頭結尾、環視

單詞邊界

  在文本處理中可能會常常進行單詞替換,好比把row替換成line。可是,若是直接替換,不只全部單詞row都被替換成line,單詞內部的row也會被替換成line。要想解決這個問題,必須有辦法肯定單詞row,而不是字符串row

  爲了解決這類問題,正則表達式提供了專用的單詞邊界(word boundary),記爲\b,它匹配的是'單詞邊界'位置,而不是字符。\b匹配的是一邊是單詞字符\w,一邊是非單詞字符\W的位置

  與\b對應的還有\B,表示非單詞邊界,但實際上\B不多使用

console.log(/\ban\b/.test('an apple'));//true
console.log(/\ban\b/.test('a an'));//true
console.log(/\ban\b/.test('an'));//true
console.log(/\ban\b/.test('and'));//false
console.log(/\ban\b/.test('ban'));//false

起始結束

  常見的斷言還有^和$,它們分別匹配字符串的開始位置和結束位置,因此能夠用來判斷整個字符串可否由表達式匹配

//匹配第一個單詞
console.log(/^\w*/.exec('first word\nsecond word\nthird word'));//['first']
//匹配最後一個單詞
console.log(/\w*$/.exec('first word\nsecond word\nthird word'));//['word']
console.log(/^a$/.test('a\n'));//false
console.log(/^a$/.test('a'));//true

  ^和$的經常使用功能是刪除字符串首尾多餘的空白,相似於字符串String對象的trim()方法

function fnTrim(str){
    return str.replace(/^\s+|\s+$/,'')
}  
console.log(fnTrim('      hello world   '));//'hello world'

環視

  環視(look-around),可形象地解釋爲停在原地,四處張望。環視相似於單詞邊界,在它旁邊的文本須要知足某種條件,並且自己不匹配任何字符

  環視分爲正序環視和逆序環視,而javascript只支持正序環視,至關於只支持向前看,不支持往回看

  而正序環視又分爲確定正序環視和否認正序環視

  確定正序環視的記法是(?=n),表示前面必須是n才匹配;否認正序環視的記憶法是(?!n),表示前面必須不是n才匹配

console.log(/a(?=b)/.exec('abc'));//['a']
console.log(/a(?=b)/.exec('ac'));//null
console.log(/a(?!b)/.exec('abc'));//null
console.log(/a(?!b)/.exec('ac'));//['a']

console.log(/a(?=b)b/.exec('abc'));//['ab']

  [注意]環視雖然也用到括號,卻與捕獲型分組編號無關;但若是環視結構出現捕獲型括號,則會影響分組

console.log(/ab(?=cd)/.exec('abcd'));['ab']
console.log(/ab(?=(cd))/.exec('abcd'));['ab','cd']

 

匹配模式

  匹配模式(match mode)指匹配時使用的規則。設置特定的模式,可能會改變對正則表達式的識別。前面已經介紹過建立正則表達式對象時,能夠設置'm'、'i'、'g'這三個標誌,分別對應多行模式、不區分大小模式和全局模式三種

i

  默認地,正則表達式是區分大小寫的,經過設置標誌'i',能夠忽略大小寫(ignore case)

console.log(/ab/.test('aB'));//false
console.log(/ab/i.test('aB'));//true

m

  默認地,正則表達式中的^和$匹配的是整個字符串的起始位置和結束位置,而經過設置標誌'm',開啓多行模式,它們也能匹配字符串內部某一行文本的起始位置和結束位置

console.log(/world$/.test('hello world\n')); //false
console.log(/world$/m.test('hello world\n')); //true

console.log(/^b/.test('a\nb')); //false
console.log(/^b/m.test('a\nb')); //true

g

  默認地,第一次匹配成功後,正則對象就中止向下匹配了。g修飾符表示全局匹配(global),設置'g'標誌後,正則對象將匹配所有符合條件的結果,主要用於搜索和替換

console.log('1a,2a,3a'.replace(/a/,'b'));//'1b,2a,3a'
console.log('1a,2a,3a'.replace(/a/g,'b'));//'1b,2b,3b'

 

優先級

  正則表達式變幻無窮,都是由以前介紹過的字符組、括號、量詞等基本結構組合而成的

//從上到下,優先級逐漸下降
\                            轉義符
() (?!) (?=) []              括號、字符組、環視
* + ? {n} {n,} {n,m}         量詞
^ $                          起始結束位置
|                            選擇

  因爲括號的用途之一就是爲量詞限定做用範圍,因此優先級比量詞高

console.log(/ab{2}/.test('abab'));//false
console.log(/(ab){2}/.test('abab'));//true

  [注意]選擇符'|'的優先級最低,比起始和結束位置都要低

console.log(/^ab|cd$/.test('abc'));//true
console.log(/^(ab|cd)$/.test('abc'));//false

 

侷限性

  儘管javascript中的正則表達式功能比較完備,但與其餘語言相比,缺乏某些特性

  下面列出了javascript正則表達式不支持的特性

  【1】POSIX字符組(只支持普通字符組和排除型字符組)

  【2】Unicode支持(只支持單個Unicode字符)

  【3】匹配字符串開始和結尾的\A和\Z錨(只支持^和$)

  【4】逆序環視(只支持順序環視)

  【5】命名分組(只支持0-9編號的捕獲組)

  【6】單行模式和註釋模式(只支持m、i、g)

  【7】模式做用範圍

  【8】純文本模式


參考資料

【1】 阮一峯Javascript標準參考教程——標準庫RegExp對象 http://javascript.ruanyifeng.com/stdlib/regexp.html【2】《正則指引》【3】《精通正則表達式》【4】《javascript權威指南(第6版)》第10章 正則表達式的模式匹配【5】《javascript高級程序設計(第3版)》第5章 引用類型【6】《javascript語言精粹(修訂版)》第7章 正則表達式

相關文章
相關標籤/搜索