js中正則表達式的模式匹配


參考Javascript權威指南(第6版)第10章

1、正則表達式的定義

正則表達式有兩種定義方法,通常使用直接量方式。

(1)直接量

var pattern = /\d$/;
var pattern = /\d$/gim;

(2)RegExp()構造函數

注意轉義字符前面的"\"必須換成"\\"。
var pattern = RegExp("\\d$","gim");

正則表達式三個修飾符的含義:

字符 含義
i 不區分大小寫
g 全局匹配
m 多行匹配

正則表達式中,需要轉義的標點符號包括:^$.*+?=!😐/()[]{}

如果不記得哪些標點符號需要反斜線轉義,可以在每個標點符號前都加上反斜線“\”

2、正則表達式的字符類

字符 匹配
[...] 括號內的任意字符
[^...] 不在括號內的任意字符
. 除換行符和其他Unicode行終止符之外的任意字符
\w [a-zA-Z0-9]
\W [^a-zA-Z0-9]
\s 任何Unicode空白符
\S 任何非Unicode空白符的字符
\d [0-9]
\D [^0-9]
[\b] 退格直接量

3、正則表達式的重復字符語法

(1)貪婪匹配

盡可能多的匹配,見下表。

字符 含義
{n,m} 匹配前一項n~m次
{n,} 匹配前一項n次及以上
{n} 匹配前一項n次
? 匹配前一項0或1次,{0,1}
+ 匹配前一項1或多次,{1,}
* 匹配前一項0或多次,{0,}

(2)非貪婪匹配

在待匹配的字符后加一個問號“?”

舉例:

var str = 'aaa';
var p1 = /a+/;//貪婪匹配
var p2 = /a+?/;//非貪婪匹配
var str1 = p1.exec(str);//aaa
var str2 = p2.exec(str);//a

4、選擇-組合-引用

字符 含義
I 選擇
(...) 組合,並且該組合匹配的字符串可供引用
(?:...) 只組合,不供引用
\n 第n個可引用分組第一次匹配的字符,n為可引用分組左括號的序號,從1開始

選擇舉例:

var str1 = "abc";
var str2 = "bac";
var pattern = /ab|ac|ba|bc/;//選擇
var str11 = pattern.exec(str1);//ab
var str22 = pattern.exec(str2);//ba
alert(str11+"---"+str22);

組合、只組合舉例:

//exec返回一個數組:元素0是與正則表達式匹配的字符串,余下元素是與圓括號內的子表達式相匹配的子串
//例1
var str = "aaaabaabcdcdef";
var p1 = /(a+b)+(cd)+/;//組合
var p2 = /(a+b)+(?:cd)+/;//只組合
var str1 = p1.exec(str);//aaaabaabcdcd,aab,cd 
var str2 = p2.exec(str);//aaaabaabcdcd,aab
alert(str1+"---"+str2);
//例2
var str = "agtAGe4545";
var p1 = /[a-zA-Z]*(\d+)/;//組合從字符串中抽取右側數字
var p2 = /[a-zA-Z]*(?:\d+)/;//只組合,無法抽取右側數字
var str1 = p1.exec(str);//agtAGe4545,4545
var str2 = p2.exec(str);//agtAGe4545
alert(str1+"---"+str2);

\n舉例:

var str1 = "JavaScript9900script";
var str2 = "JavaScript9900Script";
var p1 = /([Jj]ava([Ss]cript))\d*\2/;//組合([Jj]ava([Ss]cript))
var p2 = /(?:[Jj]ava([Ss]cript))\d*\1/;//只組合(?:[Jj]ava([Ss]cript))
var str11 = p1.exec(str1);//null
var str22 = p1.exec(str2);//JavaScript9900Script,JavaScript,Script
var str33 = p2.exec(str2);//JavaScript9900Script,Script
alert(str11+"---"+str22+"---"+str33);

5、錨字符

字符 含義
^ 字符串開頭
$ 字符串結尾
\b 單詞邊界或開頭或結尾
\B 非單詞邊界
(?=p) 零寬正向先行斷言,接下來的字符與p匹配
(?!p) 零寬負向先行斷言,接下來的字符不與p匹配

開頭、結尾舉例:

var str1 = "abbc";
var str2 = "fbbcd";
var p1 = /^a[\w]+c$/;
var p2 = /[\w]+c$/;
var str11 = p1.exec(str1);//abbc
var str22 = p2.exec(str2);//null
alert(str11+"---"+str22);

單詞邊界與非單詞邊界舉例:

var str1 = "javascript is good";
var str2 = "java is good";
//匹配java單詞本身,而javascript中的java不進行匹配
var p1 = /\bjava\b/;//\b匹配單詞邊界或開頭或結尾
var str11 = p1.exec(str1);//null
var str22 = p1.exec(str2);//java
alert(str11+"---"+str22);
//匹配javascript中的java,java單詞本身不進行匹配
var p2 = /java\B/;//\B匹配非單詞邊界
var str33 = p2.exec(str1);//java
var str44 = p2.exec(str2);//null
alert(str33+"---"+str44);

零寬正/負向先行斷言舉例:

var str = 'javascriptTool';
var p1 = /java(?=script)([a-z]\w*)/;
var p2 = /java(?!script)([a-z]\w*)/;
var str1 = p1.exec(str);//["javascriptTool","scriptTool"]
var str2 = p2.exec(str);//null

6、RegExp對象

5個屬性和3個方法

  • global:boolean,是否有“g”屬性
  • ignoreCase:boolean,是否有“i”屬性
  • multiline:boolean,是否有“m”屬性
  • lastIndex:下一個匹配開始的位置
  • source:正則表達式的文本

(1)exec

pattern.exec(str)

下面兩種情況,exec總是包含它返回的數組中的每個匹配項的全部細節。
情況一:pattern是非全局模式
沒有找到任何匹配則返回null;
找到匹配則返回數組(非全局檢索),數組的元素0是與正則表達式匹配的字符串,余下元素是與圓括號內的子表達式相匹配的子串。該數組除了有一般的length屬性外,還有index屬性(返回匹配文本的第一個字符位置)和input屬性(返回輸入的str)。
情況二:pattern是全局模式
將從pattern的lastIndex屬性指定的位置開始搜索,找到一個匹配項后,將lastIndex設為該匹配項之后的第一個字符的位置。這使得可以重復循環調用exec(),遍歷一個字符串中所有匹配項。如果exec()找不到匹配項,則返回null,並將lastIndex重置為0。注意:如果在成功找到一個字符串的匹配項之后,立刻開始搜索另一個新字符串,必須手動將lastIndex重置為0。
舉例:

var str = "agtAGe45agt67";
var p1 = /[a-zA-Z]*(\d+)/;
var str1 = p1.exec(str);
$('body').append("非全局<br>");
$('body').append("str1.input="+str1.input+"<br>");
$('body').append("str1.index="+str1.index+"<br>");
$('body').append("str1="+str1+"<br>");
//$('body').append("str1.length="+str1.length+"<br>");
$('body').append("p1.lastIndex="+p1.lastIndex+"<br>");
var p2 = /[a-zA-Z]*(\d+)/g;//全局
$('body').append("全局<br>");
while((str2 = p2.exec(str))!=null){
	$('body').append("-------------------<br>");
	$('body').append("str2.input="+str2.input+"<br>");
	$('body').append("str2.index="+str2.index+"<br>");	
	$('body').append("str2="+str2+"<br>");
	//$('body').append("str2.length="+str2.length+"<br>");
	$('body').append("p2.lastIndex="+p2.lastIndex+"<br>");	
}

結果:

非全局
str1.input=agtAGe45agt67
str1.index=0
str1=agtAGe45,45
p1.lastIndex=0
全局
-------------------
str2.input=agtAGe45agt67
str2.index=0
str2=agtAGe45,45
p2.lastIndex=8
-------------------
str2.input=agtAGe45agt67
str2.index=8
str2=agt67,67
p2.lastIndex=13

(2)test

pattern.test(str)

如果匹配返回true,反正返回false

(3) toString

pattern.toString()

使用正則表達式直接量的格式返回一個正則表達式的字符串表示

7、用於模式匹配的String方法

str.search(pattern);//pattern可以為字符串

返回第一個與pattern匹配的子串的起始位置;如果找不到子串,則返回-1。不支持全局檢索,因為它忽略正則表達式中的g。
舉例:

var str = "abcdefg123456";
var r = str.search(/\d/);//7

(2) replace

情況一:

str.replace(pattern,str2);

如果pattern中有g,則替換str中所有與pattern匹配的子串為str2;
如果無g,則只替換str中第一個與pattern匹配的子串為str2。
str2中的"$"含義見下表。

字符 替換
$1,$2,...,$99 匹配第1~99個pattern中的圓括號子表達式的文本
$& 匹配pattern的子串
$` 匹配子串的左邊文本
$' 匹配子串的右邊文本
$$ 美元符號

舉例:確保“JavaScript”大小寫正確

var str = "javascript javAScript";
var p1 = /javascript/i;//非全局,只替換第一個匹配的
var p2 = /javascript/gi;//全局,替換所有匹配的
var r1 = str.replace(p1,"JavaScript");//JavaScript javAScript
var r2 = str.replace(p2,"JavaScript");//JavaScript JavaScript
alert(r1+"---"+r2);

舉例1:將一個名字從"Doe,John"轉換為"John Doe"

var str = "Doe,John";
var pattern = /([a-zA-z]+)\s*\,\s*([a-zA-z]+)/;
var r = str.replace(pattern,"$2 $1");//John Doe
alert(r);

舉例2:將成對雙引號替換為成對單引號

var str = "\"Doe,John\"\"Doe,John\"";
var pattern = /\"([^\"]*)\"/g;
var r = str.replace(pattern,"\'$1\'");//'Doe,John''Doe,John'
alert(str+"---"+r);//"Doe,John""Doe,John"---'Doe,John''Doe,John'

情況二:

str.replace(str1,str2);

如果第一個參數是字符串而非正則表達式,則只有第一個str1替換為str2。
舉例:

var str = "javascript javascript";
//使用字符串,則只替換第一個匹配的。
var r = str.replace("javascript","JavaScript");//JavaScript javascript
alert(r);

情況三:

str.replace(pattern,func);

如果第二個參數是函數,則func將在每個匹配結果上調用,func返回的字符串則將作為替換文本。傳入func的第一個參數是匹配pattern的字符串,剩下的參數(可能有0或多個)是匹配該pattern的某個圓括號子表達式的字符串,下一個參數為str中出現匹配結果的位置,最后一個參數是str本身。
舉例:將一個字符串中所有單詞的首字母大寫

var str = "this is a demo";
var pattern = /\b[a-zA-Z]+\b/g;
var r = str.replace(pattern,function(word){
	return word.substring(0,1).toUpperCase()+word.substring(1);
});//This Is A Demo
alert(r);

(3) match

match是最常用的String正則表達式方法。

str.match(pattern);

如果pattern中有g,則返回的數組包含所有匹配結果;
如果無g,則返回的數組的元素0是第一個匹配結果,余下元素是pattern中圓括號子表達式。
可見,對於一個非全局pattern,str.math(pattern)與pattern.exec(str)的結果一樣。返回的數組有兩個屬性(與exec相同):index和input。
舉例:

var str = 'js is good';
var p1 = /\b([\w])+\b/;//非全局
var r1 = str.match(p1);
$('body').append(r1+'<br>');//js,s
$('body').append(r1.index+'<br>');//0
$('body').append(r1.input+'<br>');//js is good
var p2 = /\b[\w]+\b/g;//全局
var r2 = str.match(p2);
$('body').append(r2+'<br>');//js,is,good
$('body').append(r2.index+'<br>');//undefined
$('body').append(r2.input+'<br>');//undefined

舉例:獲取url的各個部分

var url = /(\w+):\/\/([\w.]+)\/(\S*)/;
var text = 'visit blog at http://www.example.com/~david';
var result = text.match(url);
if(result!=null){
	var fullurl = result[0];
	var protocol = result[1];
	var host = result[2];
	var path = result[3];
}
$('body').append(fullurl+'<br>');//http://www.example.com/~david
$('body').append(protocol+'<br>');//http
$('body').append(host+'<br>');//www.example.com
$('body').append(path+'<br>');//~david

(4) split

String.split()是Array.join()的反方法。

str.split(pattern,limit)//pattern可以為字符串

將str拆分為一個子串組成的數組,子串不包含pattern本身(特例除外)。limit為可選參數,指定返回數組的最大長度。
特例:如果pattern是一個包含圓括號表達式的正則表達式,則匹配這些圓括號表達式的子串(但不是匹配整個pattern的文本)將包含在返回數組中。
例1:

var str1 = "1|2|3";
var str2 = "|1|2|3|"
var r1 = str1.split("|");//1,2,3
var r2 = str2.split("|");//,1,2,3,
$('body').append(r1+'<br>');
$('body').append(r2+'<br>');

例2:

//句子切分為單詞
var str1 = "js is good";
var r1 = str1.split(/\s+/);
$('body').append(r1+'<br>');//js,is,good
//單詞切換為單一字母
var str2 = "good";
var r2 = str2.split("");
var r3 = str2.split("",2);
$('body').append(r2+'<br>');//g,o,o,d
$('body').append(r3+'<br>');//g,o

例3:希望返回的數組包含分隔符,則pattern應使用圓括號

var str = "ab12cd34ef";
var p1 = /\d+/;
var r1 = str.split(p1);
$('body').append(r1+'<br>');//ab,cd,ef
var p2 = /(\d+)/;//帶圓括號
var r2 = str.split(p2);
$('body').append(r2+'<br>');//ab,12,cd,34,ef


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM