總結(jié)JavaScript的正則與其他語言的不同之處_第1頁
總結(jié)JavaScript的正則與其他語言的不同之處_第2頁
總結(jié)JavaScript的正則與其他語言的不同之處_第3頁
總結(jié)JavaScript的正則與其他語言的不同之處_第4頁
總結(jié)JavaScript的正則與其他語言的不同之處_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、總結(jié)JavaScript的正則與其他語言的不同之處前言最近發(fā)現(xiàn)JavaScript中的正則在某些地方的表現(xiàn)和其他語言或工具中的正則有些不同,比較另類.雖然你幾乎不可能寫出也幾乎用不到下面我講的這些正則,但是了解一下畢竟是好的.本文中的代碼示例都是在兼容ES5的JavaScript環(huán)境中執(zhí)行的,也就是說,IE9之前版本,Fx4左右的版本,等,中的表現(xiàn)很有可能和我下面講的不一樣.1.空字符類不包含任何字符的字符類稱之為空字符類(empty char class),我相信你沒聽別人這么叫過,因為在其他語言中,這種寫法是非法的,所有的文檔和教程都不會講一種非法的語法.下面我演示一下其他語言或工具都是怎

2、么報這個錯的:?123456789101112131415$echo | grep ''grep: Unmatched or $echo | sed '/'sed:-e 表達式 #1,字符 4:未終止的地址正則表達式$echo | awk '/'awk: cmd. line:1: /awk: cmd. line:1: unterminated regexpawk: cmd. line:1: error: Unmatched or : /$echo | perl -ne '/'Unmatched in regex; marked b

3、y <- HERE in m/ <- HERE / at -e line 1.$echo | ruby -ne '/'-e:1: empty char-class: /$python -c 'import re;re.match("","")'Traceback (most recent call last):File "<string>", line 1, in <module>File "E:Pythonlibre.py", line 137,

4、 in matchreturn _compile(pattern, flags).match(string)File "E:Pythonlibre.py", line 244, in _compileraise error, v # invalid expressionsre_constants.error: lar expression而在JavaScript中,空字符類是合法的正則組成部分,不過它的效果是"永不匹配",也就是匹配什么都會失敗.相當于一個空否定正向環(huán)視(empty negative lookahead)(?!)的效果:?1234js&g

5、t; "whatevern".match(/g) /空字符類,永不匹配nulljs> "whatevern".match(/(?!)/g) /空否定正向環(huán)視,永不匹配null很顯然,這種東西在JavaScript中沒什么用.2.否定空字符類不包含任何字符的否定字符類稱之為否定空字符類(negative empty char class)或者叫空否定字符類(empty negative char class),都可以,因為這個名詞是我"自創(chuàng)"的,和上面講的空字符類類似,這種寫法在其他語言中也是非法的:?12345678910111

6、213141516$echo | grep ''grep: Unmatched or $echo | sed '/'sed:-e 表達式 #1,字符 5:未終止的地址正則表達式$echo | awk '/'awk: cmd. line:1: /awk: cmd. line:1: unterminated regexpawk: cmd. line:1: error: Unmatched or : /$echo | perl -ne '/'Unmatched in regex; marked by <- HERE in m/ &

7、lt;- HERE / at -e line 1.$echo | ruby -ne '/'-e:1: empty char-class: /$python -c 'import re;re.match("","")'Traceback (most recent call last):File "<string>", line 1, in <module>File "E:Pythonlibre.py", line 137, in matchreturn _com

8、pile(pattern, flags).match(string)File "E:Pythonlibre.py", line 244, in _compileraise error, v # invalid expressionsre_constants.error: lar expression$而在JavaScript中,否定空字符類是合法的正則組成部分,它的效果和空字符類的效果剛剛相反,它可以匹配任意的字符,包括換行符"n" ,也就是說,等同于常見的sS和wW :?1234js> "whatevern".match(/g

9、) /否定空字符類,匹配任意字符"w", "h", "a", "t", "e", "v", "e", "r", "n"js> "whatevern".match(/sS/g) /互補字符類,匹配任意字符"w", "h", "a", "t", "e", "v", "

10、e", "r", "n"需要注意的是,它不能稱之為是"永匹配正則",因為字符類必須要有一個字符才可能匹配,如果目標字符串是空的,或者已經(jīng)被左邊的正則消耗完了,則匹配會失敗,比如:?12js> /abc/.test("abc") /c后面沒有字符了,匹配失敗.false想要了解真正的"永匹配正則",可以看看我以前翻譯的一篇文章:"空"正則3.和這個講起來比較簡單,就是:在Perl和其他一些linux命令的正則表達式中,字符類中如果包含了一個緊跟著左方括號的右方括

11、號 ,則這個右方括號會被當作一個普通字符,即只能匹配"",而在JavaScript中,這種正則會被識別成一個空字符類后跟一個右方括號,空字符類什么都不匹配.也類似:在JavaScript中,它匹配的是一個任意字符(否定空字符類)后跟一個右中括號,比如"a","b" ,而在其他語言中,匹配的是任何非的字符.?1234567891011$perl -e 'print "" = /'1$js -e 'print(/.test("")'false$perl -e '

12、;print "x" = /'1$js -e 'print(/.test("x")'false4.$錨點有些初學者認為$匹配的是換行符"n" ,這是大錯特錯的,$是一個零寬斷言(zero-width assertion),它是不可能匹配到一個真正的字符的,它只能匹配一個位置.我要的講的區(qū)別發(fā)生在非多行模式中:你也許會認為,在非多行模式中,$匹配的不就是最后一個字符后面的位置嗎?實際上沒那么簡單,在其他大部分語言中,如果目標字符串中的最后一個字符是換行符"n" ,則$還會匹配那個換行符之前的位

13、置,也就是匹配了末尾的換行符左右兩邊的兩個位置.很多語言中都有Z和z這兩個表示法,如果你知道它們之間的區(qū)別,那你應該就明白了,在其他語言中(Perl,Python,php,Java,c#.),非多行模式下的$相當于Z,而在JavaScript中,非多行模式下的$相當于z(只會匹配最末尾的那個位置,不管最后一個字符是否是換行符).Ruby是個特例,因為它默認就是多行模式,多行模式下$會匹配每個換行符前面的位置,當然也會包括結(jié)尾處可能出現(xiàn)的那個換行符.余晟著的正則指引一書中也講到了這幾點.?1234567$perl -e 'print "whatevern" = s/$

14、/替換字符/rg' /全局替換whatever替換字符 /換行符前面的那個位置被替換替換字符 /換行符后面的那個位置被替換$js -e 'print("whatevern".replace(/$/g,"替換字符")' /全局替換whatever替換字符 /換行符后面的那個位置被替換5.點號元字符"."在JavaScript中的正則表達式中,點號元字符"."可以匹配四個行終止符(r-回車符,n-換行符,u2028-行分隔符,u2029-段落分隔符)之外的所有字符,而在其他常用語言中,只會排除掉

15、換行符n.6.向前引用我們都知道正則中有反向引用(back reference),也就是用一個反斜杠+數(shù)字的形式引用到前面的某個捕獲分組已經(jīng)匹配到的字符串,目的是用來再次匹配或作為替換結(jié)果(變成$).但有種特殊情況是,如果那個被引用的捕獲分組還沒開始(左括號為界),就使用了反向引用,會怎樣.比如正則/(2(a)2/ , (a)是第二個捕獲分組,但在它的左邊使用了引用它的匹配結(jié)果的2,我們知道正則是從左向右進行匹配的,這就是本節(jié)的標題向前引用(forwards reference)的來歷,它并不是一個嚴格的概念.那么現(xiàn)在你想想,下面的這句JavaScript代碼將返回什么:?12js> /

16、(2(a)2/.exec("aaa")?在回答這個問題之前,先看看其他語言中的表現(xiàn).同樣,在其他語言中,這么寫也基本上是無效的:?12345678910$echo aaa | grep '(2(a)2'grep: Invalid back reference$echo aaa | sed -r '/(2(a)2/'sed:-e 表達式 #1,字符 12:非法回引用$echo aaa | awk '/(2(a)2/'$echo aaa | perl -ne 'print /(2(a)2/'$echo aaa |

17、ruby -ne 'print $_ = /(2(a)2/'$python -c 'import re;print re.match("(2(a)2","aaa")'None在awk中沒有報錯,是因為awk不支持這種反向引用,其中的2被解釋成了ASCII碼為2的字符.而在Perl Ruby Python中沒報錯,我不知道為什么這樣設(shè)計,應該都是學Perl的,但效果都一樣,就是這種情況下是不可能匹配成功的.而在JavaScript中,不僅不報錯,還能匹配成功,看看和你剛才想的答案一樣不一樣:?12js> /(2(a)2

18、/.exec("aaa")"aa", "a", "a"防止你忘了exec方法返回的結(jié)果是什么,我說一下.第一個元素是完整的匹配字符串,也就是RegExp"$&" ,后面的是每個捕獲分組匹配的內(nèi)容,也就是RegExp.$1和RegExp.$2.為什么能匹配成功呢,匹配過程是怎樣的?我的理解是:首先進入了第一個捕獲分組(最左邊的左括號),其中第一個有效匹配項是2,然而這時第二個捕獲分組(a)還沒輪上,因此RegExp.$2的值還是undefined,所以2匹配了目標字符串中第一個a左邊的一個

19、空字符,或者說"位置",就像和其他零寬斷言一樣.重點是匹配成功了.繼續(xù)走,這時第二個捕獲分組(a)匹配到了目標字符串中的第一個a,RegExp.$2的值也被賦值為"a",然后是第一個捕獲分組結(jié)束(最右邊的右括號),RegExp.$1的值也是"a".然后是量詞2,也就是說,要從目標字符串中的第一個a之后,開始進行正則(2(a)的新的一輪匹配,很關(guān)鍵的一點在這里:就是RegExp.$2的值也就是2匹配的值還是不是第一輪匹配結(jié)束時的被賦的值"a",答案是:"不是",RegExp.$1和RegExp.$2的值都會被清空為undefined,1和2又會和第一次一樣,成功匹配一個空字符(相當于無任何效果,寫不寫都一樣).成功匹配了目標字符串中的第二個a,這時RegExp.$1和RegExp.$2的值又一次成為了"a",RegExp"$&"的值成為了完整的匹配字符串,前兩個a:"aa".在Firefox的早期版本(3.6)中,量詞的重新一輪匹配不會清空已有的捕獲分組的值,那么也就是說,在第二輪匹配的時候,2會匹配上第二個a,從而:?12j

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論