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

来源:http://www.cnblogs.com/xiaohuochai/archive/2016/06/23/5608807.html
-Advertisement-
Play Games

[1]定義 [2]特點 [3]元字元 [4]轉義字元 [5]字元組 [6]量詞 [7]括弧 [8]選擇 [9]斷言 [10]匹配模式 [11]優先順序 [12]局限性 ...


×
目錄
[1]定義 [2]特點 [3]元字元[4]轉義字元[5]字元組[6]量詞[7]括弧[8]選擇[9]斷言[10]模式[11]優先順序[12]局限性

前面的話

  正則表達式在人們的印象中可能是一堆無法理解的字元,但就是這些符號卻實現了字元串的高效操作。通常的情況是,問題本身並不複雜,但沒有正則表達式就成了大問題。javascript中的正則表達式作為相當重要的知識,本文將介紹正則表達式的基礎語法

 

定義

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

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

Perl寫法

  正則表達式字面量寫法,又叫Perl寫法,因為javascript的正則表達式特性借鑒自Perl

  正則表達式字面量定義為包含在一對斜杠(/)之間的字元,並且可以設置3個標誌

var expression = /pattern/flags;

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

  g:表示全局(global)模式,即模式將被應用於所有字元串,而非在發現第一個匹配項時立即停止

  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');

  [註意]ECMAScript3規範規定,一個正則表達式直接量會在執行到它時轉換為一個RegExp對象,同一段代碼所表示正則表達式直接量的每次運算都返回同一個對象。ECMAScript5規範則做了相反的規定,同一段代碼所表示的正則表達式直接量的每次運算都返回新對象。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...      反向引用            匹配之前的第一、第二...組括弧內的表達式匹配的文本

 

轉義字元

  轉義字元(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},實際上這是錯誤的,因為它包括15、16、17、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('[email protected]'));//true
    console.log(p.test('q@qq'));//false
    console.log(p.test('[email protected]'));//true

捕獲

  括弧不僅可以對元素進行分組,還會保存每個分組匹配的文本,等到匹配完成後,引用捕獲的內容。因為捕獲了文本,這種功能叫捕獲分組

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

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

  與以往不同的是,年、月、日這三個數值被括弧括起來了,從左到右為第1個括弧、第2個括弧和第3個括弧,分別代表第1、2、3個捕獲組

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

RegExp.$1\RegExp.$2\RegExp.$3……到RegExp.$9分別用於存儲第一、第二……第九個匹配的捕獲組。在調用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?\d{2};//10-99
1\d{2};//100-199
2[0-4]\d;//200-249
25[0-5];//250-255
//數字(0-255)
/(00)?\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5]/;
//ip地址
var ip = /^(((00)?\d|0?\d{2}|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章 正則表達式


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、關於頁面元素的引用 通過jquery的$()引用元素包括通過id、class、元素名以及元素的層級關係及dom或者xpath條件等方法,且返回的對象為jquery對象(集合對象),不能直接調用dom定義的方法。 2、jQuery對象與dom對象的轉換 只有jquery對象才能使用jquery定義 ...
  • 說到本地存儲,這玩意真是歷盡千辛萬苦才走到HTML5這一步,之前的歷史大概如下圖所示: 最早的Cookies自然是大家都知道,問題主要就是太小,大概也就4KB的樣子,而且IE6只支持每個功能變數名稱20個cookies,太少了。優勢就是大家 都支持,而且支持得還蠻好。很早以前那些禁用cookies的用戶也都 ...
  • 什麼是javascript? (1) JavaScript是一種基於對象(Object)和事件驅動(Event Driven)並具有安全性能的 腳本語言。 (2) JavaScript是由Netscape公司開發的一種腳本語言,其編寫的程式可以嵌入到 HTML頁面中,並直接在瀏覽器中解釋執行。 (3 ...
  • 近年來,CSS不透明算得上是一種相當流行的技術,但在跨瀏覽器支持上,對於開發者來說,可以說是一件令人頭疼的事情。目前還沒有一個通用方法,以確保透明度設置可以在目前使用的所有瀏覽器上有效。 這篇彙總主要是提供一些CSS不透明的詳細介紹,代碼示例和解釋,以實現這項有用的CSS技術在您的項目中相容所有瀏覽 ...
  • [1]對象 [2]實例屬性 [3]構造函數屬性 [4]實例方法 ...
  • 使用EasyUi我們可以在客戶端表單提交之前進行驗證,過程如下:只需在onSubmit的時候使用return $("#form1").form('validate')方法即可,EasyUi中form模塊中的from('validate')方法會自行對我們指定的表單中required=true等需要驗 ...
  • 作者:vousiu 出處:http://www.cnblogs.com/vousiu 本實例參考自Mike Cantelon等人的《Node.js in Action》一書。 server.js 跟前文所說過的原因一樣,我認為此處的cache可以不作為參數傳進來。此處由於是傳引用因此不影響。但若傳的 ...
  • 作者:vousiu 出處:http://www.cnblogs.com/vousiu 本實例參考自Mike Cantelon等人的《Node.js in Action》一書。 index.html style.css ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...