摘要:正則表達式的意義中的正則表達式使用表示,可以使用構造函數來創建對象,不過對象更多的是通過一種特殊的直接量語法來創建。用構造函數也可以定義一個與之等價的正則表達式,代碼如下正則表達式的模式規則是由一個字符序列組成的。
正則表達式的模式匹配
正則表達式(regular expression)是一個描述字符模式的對象。javascript的RegExp對象表示正則表達式,String和RegExp都定義了方法,后者使用正則表達式進行強大的模式匹配和文本檢索與替換功能。Javascript的正則表達式是Perl5的正則表達式語法的大型子集,所以對于有Perl編程經驗的程序員來說。學習Javascript的正則表達式是小菜一碟。
正則表達式的意義Javascript中的正則表達式使用RegExp表示,可以使用RegExp()構造函數來創建RegExp對象,不過RegExp對象更多的是通過一種特殊的直接量語法來創建。就像通過引號包裹字符的方式來創建字符串直接量一樣。正則表達式直接了定義為包含在一對斜杠(/)之間的字符,例如:
var patterns = /s$/;
運行這段代碼創建一個新的RegExp對象,并將它賦值給變量patterns。這個特殊的RegExp對象用來匹配所有以字符“s”結尾的字符串。用構造函數RegExp也可以定義一個與之等價的正則表達式,代碼如下:
var pattern = new RegExp("s$");
正則表達式的模式規則是由一個字符序列組成的。包括所有字母和數字在內,大多數的字符都是按照直接量僅描述匹配的字符的。如此說來,正則表達式/java/可以匹配任何包含“java”子串的字符串。除此之外,正則表達式中還有其他具有特殊語義的字符,這些字符并不按照字面含義進行匹配。比如,正則表達式/s$/包含兩個字符,第一個字符“s”按照字面含義匹配,第二個字符“$”是一個具有特殊語義的字符,用以匹配字符串的結束。因此這個表達式可以匹配任何以“s”結束的字符串。
RegExp直接量和對象的創建就像字符和數字一樣,程序中每個取值相同的原始類型直接量均表示相同的值,這是顯而易見的。程序運行時每次遇到對象直接量(初始化表達式)諸如{}和[]的時候都會創建新對象。比如,如果在循環體中寫var a = [];,則每次遍歷都會創建一個新的空數組。
正則表達式直接量則與此不同,ECMAScript 3規范規定,一個正則表達式直接量會在執行到它時轉換為一個RegExp對象,同一段代碼所表示正則表達式直接量的每次運算都返回同一個對象。ECMAScript 5規范則做了相反的規定,同一段代碼所表示的正則表達式直接量的每次運算都返回新對象。IE一直都是按照ECMAScript 5的規范實現的,多數最新版本的瀏覽器也開始遵循ECMAScript 5,盡管目前該標準并為全面廣泛推行。如下列代碼:
function getReg() { var reg = /[a-z]/; reg.foo = "bar"; return reg; } var reg = getReg(); var reg2 = getReg(); console.log(reg === reg2); // 在Firefox 3.6中返回true,在Firefox 4+中返回flase reg.foo = "baz"; console.log(reg2.foo); // 在Firefox 3.6中返回“baz”,在Firefox 4+中返回“bar”
原因可以在ECMAScript 5規范第24頁和第247頁中找到,也就是說在ECMAScript 3規范中,用正則表達式創建的RegExp對象會共享一個實例,而在ECMAScript 5中則是兩個獨立的實例。很明顯ECMAScript 5的規范更符合開發者的期望。
直接量字符串正如上文提到的,正則表達式中的所有字母和數字都是按照字面含義進行匹配的。JavaScript正則表達式也支持非字母的字符匹配,這些字符通過反斜線()作為前綴進行轉義。比如,轉義字符n用來匹配換行符。
o NUL字符(u0000)
t 制表符(u0009)
n 換行符(u000A)
v 垂直制表符(u000B)
f 換頁符(u000C)
r 回車符(u000D)
xnn 有十六進制數nn指定為拉丁字符,例如,x0A等價于n
uxxxx 由十六進制數xxxx指定的Unicode字符,例如u0009等價于t
cX 控制字符^X,例如,cJ等價于換行符n
在正則表達式中,許多(共18個)標點符號具有特殊含義,它們是
^ $ . * + ? : ! = / | [ ] { } ( )
在接下來的幾節里,我們將學習這些符號的含義,某些符合只有在正則表達式的某些上下文中才具有特殊含義,在其他上下文中則被當成直接量處理。然而,如果想在正則表達式中使用這些字符的直接量進行匹配,則必須使用前綴``,這是一條通用的規則。其他標點符號(比如@和引號)沒有特殊含義,在正則表達式中按照字面含義進行匹配。
如果不記得那些標點符號需要反斜線轉移,可以使用每個標點符號前都加上反斜線。另外需要注意,許多字符和數字在有反斜線做前綴是也有特殊含義`,所以對于想按照直接量進行匹配的字母和數字,進行不要用反斜線對其轉義。當然,想要在正則表達式中按照直接量匹配反斜線本身,則必須使用反斜線將其轉義。比如,正則表達式“//”用以匹配任何包含反斜線的字符串。
字符類將直接量字符串多帶帶放進方括號內就組成了字符類(character class)。一個字符類可以匹配它所包含的任意字符。因此,正則表達式/[abc]/就和字母“a”、“b”、“c”中的任意一個都匹配。定義否定字符類時,將一個“^”字符做為左方括號內的第一字符。正則表達式/[^abc]/匹配的是“a”、“b”、“c”之外的所有字符。字符類可以使用連字符來表示字符范圍。要匹配拉丁字母表中的小寫字母,可以使用/[a-z]/,要匹配拉丁字母表中任何字母和數字,則使用/[a-zA-Z0-9]/。
由于某些字符類非常常用,因為在JavaScript的正則表達式語法中,使用了這些特殊字符的轉義字符來表示它們。例如,s匹配的是空格符、制表符和其他Unicode空白符(o、 、 、 v、 f、 等),S匹配的是非Unicode 空白符的字符。下面列出了這些字符,并且總結了字符類的語法(注意,有些字符類轉義字符只能匹配ASCII字符,還沒有擴展到可以處理Unicode字符,但可以通過十六進制表示方法來顯示定義Unicode字符類,例如,/[u2e80-u9fff]/用來匹配所有漢字)。
[...] 方括號內的任意字符
[^...] 不在方括號內的任意字符
. 除換行符和其他Unicode行終止符之外的任意字符
w 任何ASCII字符組成的單詞,等價于[a-zA-Z0-9]
W 任何不適ASCII字符組成的單詞,等價于[^a-zA-Z0-9]
s 任何Unicode空白符
S 任何非Unicode空白符的字符,注意W和S的不同
d 任何ASCII數字,等價于[0-9]
D 除了ASCII數字之外的任何字符,等價于[^0-9]
[b] 推格直接量(特例)
注意,在方括號之內也可以寫這些特殊轉義字符。比如,由于s匹配所有的空白符,d匹配的是所有數字,因為/[ds]/匹配的就是任意空白符或者數字。注意,這里有一個特例。下面我們將會看到轉義符具有的特殊含義,當用在字符類時,它表示的是退格字符,所以要在正則表達式中按照直接量表示一個退格符,只需要使用具有一個元素的字符類/[]/。
重復用剛剛學過的正則表達式的語法,可以把兩位數描述成/dd/,四位數描述成/ffffdd/。但是目前為止,還沒有一種方法可以用來描述任意多位的數字活著描述由三個字母和一個數字構成的字符串。這些正則表達式語法中較為復雜的模式都提到了正則表達式中某元素的"重復出現次數"。
我們在正則模式之后跟隨用以制定字符重復的標記。由于某些重復種類非常常用,因此就有一些專門用于表示這種情況的特殊字符。例如,“+”用以匹配前一個模式的一個或多個副本。下面總結了這些表示重復的正則語法。
{n,m} 匹配前一項至少n次,但不能超過m次
{n,} 匹配前一項n次或者更多次
{n} 匹配前一項n次
? 匹配前一項0次或者1次,也就是說前一項是可選的,等價于{0,1}
+ 匹配前一項1次或者多次,等價于{1,}
* 匹配前一項0次或者多次,等價于{0,}
這里有一些例子:
var reg1 = /d{2,4}/ // 匹配2~4個數字 var reg2 = /w{3}d?/ // 精確匹配三個單詞和一個可選數字 var reg3 = /s+javas+/ // 匹配前后帶有一個或多個空格的字符串“java” var reg4 = /[^(]*/ // 匹配一個或多個非左括號的字符
在使用“*”和“?”時要注意,由于這些字符可能匹配0個字符,因此它們允許什么都不匹配。例如,正則表達式/a*/實際與字符串“bbbb”匹配,因為這個字符串含有0個a。
非貪婪的重復上面列出的匹配重復字符是盡可能多的匹配,而且允許后續的正則表達式繼續匹配。因此,我們稱之為“貪婪的”匹配。我們同樣可以使用正則表達式進行非貪婪匹配。只須在待匹配的字符后跟隨一個問號即可:“??”、“+?”、“*?”或“{1,5}?”。比如,正則表達式/a+/可以匹配一個或多個連續的字符a。當使用“aaa”作為匹配字符串時,正則表達式會匹配它的三個字符。但是/a+?/也可以匹配一個或多個連續字母a,但它是盡可能少地匹配。我們同樣將“aaa”作為匹配字符串,但后一個模式只能匹配第一個a。
使用非貪婪的匹配模式所得到的結果可能和期望并不一致??紤]以下正則表達式/a+b/,它可以匹配一個或多個a,以及一個b。當使用“aaab”作為匹配字符串時,她會匹配整個字符串,現在再試一下非貪婪匹配的版本/a+?b/,它匹配盡可能少的a和一個b。當用它來匹配“aaab”時,你期望它能匹配一個a和最后一個b。但實際上,這個模式卻匹配了整個字符串,和該模式的貪婪匹配一摸一樣。這是因為正則表達式的模式匹配總是會尋找字符串中第一個可能匹配的位置。由于該匹配是從字符串的第一個字符開始的。因此在這里不考慮他的子串中更短的匹配。
選擇、分組和引用正則表達式的語法還包括制定選擇項、子表達式分組和引用前一個子表達式的特殊字符。字符“|”用于分割供選擇的字符。例如,/ab|cd|ef/可以匹配“ab”,可以可以匹配符串“cd”,還可以匹配字符串“ef”。/d{3}|[a-z]{4}/匹配的時三位數字或者四個小寫字母。
注意,選擇項的嘗試匹配次序是從左到右,直到發現匹配項。如果左邊的選擇項匹配,就會忽略右邊的匹配項,即使它產生更好的匹配。因此,當正則表達式/a|ab/匹配字符串“ab”時,它只能匹配第一個字符。
正則表達式中的圓括號有多種作用。第一個作用是把多帶帶的項組合成子表達式,以便可以像處理一個獨立的單元那樣用“|”、“ * ”、“ + ”或者“ ? ”等來對單元內的項進行處理。例如,/java(Script)?/可以匹配字符串“java”,其后可以有“Script”也可以沒有。/(ab|cd)+|ef/可以匹配字符串“ef”,也可以匹配字符串“ab”或者“cd”的一次或多次重復。例如,將“font-size”改為“fontSize”:
var str = "font-size"; str = str.replace(/-(w)/,function(str,$1){ return $1.toUpperCase(); }); console.log(str); // => fontSize
在正則表達式中,圓括號的另一個作用是在完整的模式中定義子模式。當一個正則表達式成功地和目標字符串相互匹配時,可以從目標字符串中抽出和圓括號匯總的字母是相匹配的部分(我們將在隨后的部分中看到如何取得這些匹配的子串)。例如,嘉定我們正在檢索的模式是一個或多個小寫字母后面跟隨了一位或多位數字,則可以使用模式/[a-z]+d+/。但假定我們真正關心的是每個匹配尾部的數字,那么如果將模式的數字部分放在括號中(/[a-z]+(d+)/),就可以從檢索到的匹配中抽取數字了。如下:
var reg = /[a-z]+d+/; var str = "abcde123"; str.match(reg); // => ["abcde123"] var reg2 = /[a-z]+(d+)/; str.match(reg2); // => ["abcde123", "123"]
帶圓括號的表達式的另一個用途就是允許在同一正則表達式的后部引用前面的子表達式。這是通過在字符“”后加一位或多位數字來實現的。這個數字指定了帶圓括號的子表達式在正則表達式中的位置。例如,1引用的是第一個帶圓括號的子表達式,3引用的是第三個帶圓括號的子表達式。注意,因為子表達式可以嵌套另外一個子表達式,所以它的問題是參與計數的左括號的位置。例如,下面的正則表達式中,嵌套的子表達式([Ss]cript)可以使用2來指代
var reg = /([Jj]ava([Ss]cript)?)siss(funw*)/; var str = "javascript is fun that java"; var match = str.match(reg); console.log(match); // => ["javascript is fun", "javascript", "script", "fun"]
對正則表達式中前一個子表達式的引用,并不是只對子表達式的引用,而是指與那個模式相匹配的文本的引用。這樣,引用可以用于實施一條約束,即一個字符串各個多帶帶部分包含的是完全相同的字符。例如,下面的正則表達式匹配的就是位于單引號或雙引號之內的0個或多個字符。但是,它并不要求左側和右側的引號匹配(即加入的兩個引號都是單引號或都是雙引號):
var reg = /[""][^""]*[""]/; var str = ""hello""; reg.test(str); // => true
如果要匹配左側和右側的引號完全相同,可以使用如下引用:
var reg = /([""])[^""]*1/; var str = ""hello""; reg.test(str); // => false
因為左側和右側的引號不一致,所以false。1匹配的是第一個帶圓括號的子表達式所匹配的模式。在這個例子中,存在這樣一條約束,那就是左側的引號必須和右側的引號相匹配。正則表達式不允許用雙引號括起來的內容有單引號,反之亦然。不能在字符類中使用這種引用,所以下面的寫法是非法的:
var reg = /([""])[^1]*1/; var str = ""hello""; reg.test(str); // => false
正如上面重點標注的那段說明。對正則表達式中前一個子表達式的引用,并不是只對子表達式的引用,而是指與那個模式相匹配的文本的引用 所以這個是false。
在接下來,我們會看到一種帶圓括號的子表達式的引用,這是正則表達式的檢索和替換操作的強大特性之一。
同樣,在正則表達式中不用創建帶數字編碼的引用,也可以對子表達式進行分組。它不是以“ ( ”和“ ) ”進行分組,而是以“ (?: ”和“ ) ”來進行分組,比如,考慮下面這個模式:
var reg = /([Jj]ava(?:[Ss]cript)?)siss(funw*)/; var str = "javascript is fun that java"; var match = str.match(reg); // => ["javascript is fun", "javascript", "fun"]
我們會發現這里匹配的結果跟前面匹配的結果“["javascript is fun", "javascript", "script", "fun"]”相比,少了一個"script"。這是因為子表達式(?:[sS]cript)僅僅用于分組,不參與引用。因此復制符號"?"可以應用到各個分組。這種改進的圓括號并不生成引用,所以這個正則表達式中,2引用了與(funW*)匹配的文本。
下面是對正則表達式的選擇、分組和引用運算符做了總結。
指定匹配位置| 選擇,匹配的是該符號左邊的子表達式或右邊的子表達式
(...) 組合,將幾個項組合為一個單元,這個單元可通過“ * ”、“ ? ”、“ + ”和“ | ”等符號加以修飾,而且可以記住和這個組合相匹配的字符串以供此后的引用使用
(?:...) 只組合,把項組合到一個單元,但不記憶和改組相匹配的字符
和第n個分組第一次匹配的字符相匹配,組是圓括號中的子表達式(也可能是嵌套的),組索引是從左到右的左括號,“(?:”形式的分組不參與編碼
正如前面所介紹的,正則表達式中的多個元素才能夠匹配字符串中的一個字符。例如,s匹配的只是一個空白符。還有一些正則表達式的元素匹配的是字符之間的位置,而不是實際的字符。例如,b匹配一個單詞的邊界,即位于w(ASCII單詞)字符和W(非ASCII單詞)之間的邊界,或位于一個ASCII單詞與字符串的開始或結束之間的邊界。像b這樣的元素不匹配某個可見的字符,它們指定匹配發生的合法位置。有時我們稱這些元素為正則表達式的錨,因為它們將模式定位在搜索字符串的特定位置上。最常用的錨元素是^,它是用來匹配字符串的起始位置,錨元素$用以匹配字符串的結束位置。
例如,要匹配單詞“javascript”,可以使用正則表達式/^[Jj]ava[Ss]cript$/。如果想匹配"java"這個單詞本身(不像在“JavaScript”中作為單詞的前綴),可以使用正則表達式/sJava/,可以匹配前后都有空格的單詞“java”。但是這樣做有兩個問題,第一,如果“java”出現在字符串的開始或者結尾,就是匹配不成功,除非開始和結尾處各有一個空格。第二個問題是,當找到了與之匹配的字符串時,它返回的匹配字符串的前端和后端都有空格沒這并不是我們想要的。因此我們使用單詞的邊界b來代替真正的空格符s進行匹配(或定位)。這樣正則表達式就寫成了/b[Jj]avab/。元素B將把匹配的錨點定位在不適單詞的邊界之處。因此正則表達式/B[Ss]cript/于“JavaScript”和“posrscript”匹配,但是不與“script”和“Scripting” 匹配。
var reg =/java/; var str = "javascript is more fun that java"; str.match(reg); // => ["java"] var str2 = "javascript is more fun that javac"; str.match(reg); // => null
任意正則表達式都可以作為錨點條件。就像上面例子中/bjavab/中的"java"。如果在富豪“ (?= ”和“ ) ”之間加入一個表達式,他就是一個先行斷言,用以說明圓括號內的表達式必須正確匹配,但并不是真正意義上的匹配。比如,要匹配一種常用的程序設計語言的名字,但只在其后有冒號時才匹配,可以使用/[Jj]ava([Ss]cript)?(?=:)/。這個正則表達式可以匹配“Javascript: beautiful language”中的“JavaScript”,但是不能匹配“java in a Nutshell”中的“Java”,因為它后面沒有冒號。
var reg =/[Jj]ava([Ss]cript)?(?=:)/; var str1 = "Javascript: beautiful language"; str1.match(reg); // => ["Javascript", "script"] var str2 = "java in a Nutshell"; str2.match(reg); // => null
帶有“ (?! ”的斷言是負向先行斷言,用一指定接下來的字符都不必匹配。例如,/Java(?!Script)[A-Z]w*/可以匹配“Java”后跟隨一個大寫字母和任意多個ASCII單詞,但Java后不能跟隨“Script”。它可以匹配”JavaBeans“,但是不能匹配”Javanese“。
var reg = /Java(?!Script)[A-Z]w*/; var str = "JavaBeans"; str.match(reg); // => ["JavaBeans"]
修飾符^ 匹配字符串的開頭,再多行檢索中,匹配一行的開頭
$ 匹配字符串的結尾,再多行檢索中,匹配一行的結尾
匹配一個單詞的邊界,簡言之,就是位于字符w和W之間的位置,或位于字符W和匹配字符串的開頭或者結尾的位置
B 匹配非單詞邊界的位置
(?=pattern) 正向先行斷言,要就接下來的字符都與pattern匹配,但是不能包含匹配pattern的那些字符
(?!pattern) 負向(反向)先行斷言,要就接下來的字符都不與pattern匹配
正則表達式中的語法還有最后一個知識點,即正則表達式的修飾符,用以說明高級匹配模式的規則。和之前討論的正則表達式語法不同,修飾符是放在“/”符號之外的,也就是說,它們不是出現兩條斜線之間,而是第二條斜線之后。JavaScript支持三個修飾符,修飾符“i”用以說明模式匹配是不區分大小寫。修飾符“g”說明*模式匹配應該是全局的,*也就是說,應該找出被檢索字符串中所有的匹配。修飾符“m”用以在多行模式中執行匹配,在這種模式下,如果待檢索的字符串包含多行,那么^和$錨字符除了匹配整個字符串的開始和結尾之外,還能匹配每行的開始和結束。比如正則表達式/java$/im可以匹配“java”也可以匹配“Javan is fun”。
var reg = /java$/im; var str1 = "java"; str1.match(reg); // => ["java"] var str2 = "java is fun"; str2.match(reg); // => ["java"]
這些修飾符可以任意組合,比如,要想不區分大小寫匹配字符串中的第一個單詞“java”,可以使用不區分大小寫的修飾符來定義正則表達式/bjavab/i。要想匹配字符串中所有單詞,則需要添加修飾符g:/bjavab/gi。
i 執行不區分大小寫的匹配
g 執行一個全局匹配,簡言之,即找到所有的匹配,而不是在找到第一個之后停止
m 多行匹配模式,^匹配一行的開頭和字符串的開頭,$匹配行的結尾和字符串的結尾
獲取指定的querystring
function param(key, url) { var reg = new RegExp("(?:^|?|#|&)" + key + "=([^]*)(?:$|&|#)", "i"); var o = reg.exec(url || location.href); return o ? encodeURI(o[1]) : ""; }
獲取所有的querystring
function getAllParam() { var reg=/[?&]([^=?&]+)=([^=?&]+)/ig var url={}; while(reg.exec(location.href)){ url[RegExp.$1]=RegExp.$2; } return url; }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79852.html
摘要:選擇分組和引用正則表達式的語法還包括指定選擇項子表達式分組和引用前一子表達式的特殊字符。帶圓括號的表達式的另一個用途是允許在同一正則表達式的后部引用前面的子表達式。 正則表達式(regular expression)是一個描述字符模式的對象。JavaScript的 RegExp類 表示正則表達式,String和RegExp都定義了方法,后者使用正則表達式進 行強大的模式匹配和文本檢索與...
Javascript的正則表達式是前端中比較重要的部分,正則表達式主要用于字符串處理,表單驗證等場合,實用高效,文章主要對JavaScript中的正則的學習與總結 正則表達式的定義 正則表達式:是一個描述字符模式的對象,JavaScrip中正則表達式用RegExp對象表示,可以使用RegExp構造函數來創建正則對象 正則表達式的創建 1.字面量創建 var reg = /[a-z]/; 2.構...
摘要:正則表達式的字符串表示,按照字面量形式而非傳入構造函數中的字符串模式返回。其中,表示匹配項在字符串中的位置,而表示應用正則表達式的字符串。下面列出了正則表達式所不支持的特性。關卡按要求完成下列常用的正則表達式。 由于本課程的核心是 JavaScript,所以本文著重講解了「正則表達式」在 JavaScript 中的用法,并未深入「正則表達式」的具體細節。如果您尚不了解「正則表達式」,強...
閱讀 3430·2021-11-12 10:36
閱讀 2745·2021-11-11 16:55
閱讀 2970·2021-09-27 13:36
閱讀 1620·2021-08-05 10:01
閱讀 3560·2019-08-30 15:55
閱讀 774·2019-08-30 13:01
閱讀 1914·2019-08-29 17:16
閱讀 2383·2019-08-29 16:40