文首發(fā)自「慕課網(wǎng)」,想了解更多IT干貨內(nèi)容,程序員圈內(nèi)熱聞,歡迎關(guān)注!
作者|慕課網(wǎng)精英講師 然冬
表示式亦稱表達式、運算式或數(shù)學表達式,在數(shù)學領(lǐng)域中是一些符號依據(jù)上下文的規(guī)則,有限而定義良好的組合。數(shù)學符號可用于標定數(shù)字(常量)、變量、操作、函數(shù)、括號、標點符號和分組,幫助確定操作順序以及有其它考量的邏輯語法。——Wikipedia
表達式可以簡單理解成一種式子,如 2 + 3 就是一種表達式,通常會叫做算術(shù)表達式。
通常表達式用來產(chǎn)生值,任何需要用到值的地方都可以放置表達式。
一個表達式由操作數(shù)與操作符組成,操作數(shù)可以由變量、常量或者另一個表達式表示。
如:
var a=1;
var b=2;
var c=3;
var res=((a + b) - (c * sqrt(9)));
代碼塊12345
其中第五行等號右邊就是一個算術(shù)表達式,其由多個算術(shù)表達式組成。
除了函數(shù)調(diào)用的括號,剩下所有括號包裹的都是一個表達式。(注意:表達式并不是一定要括號包括,這里是為了方便劃分)
在等號右側(cè)表達式計算完后,得到一個值,最后會賦值給變量 res,這就是一個賦值表達式。
可以見到表達式無處不在。
注意:有些文獻中會把調(diào)用函數(shù)描述為一個函數(shù)表達式。但通常在JavaScript中會把一種創(chuàng)建函數(shù)的方式描述為函數(shù)表達式,具體可以查閱函數(shù)章節(jié)。
表達式是一個基礎(chǔ)而又重要的概念,同時又比較抽象,初學者不好理解。
我個人理解的表達式,就是一種具有規(guī)則、可以得到一個結(jié)果的式子。
理解表達式主要是為學習鋪路,大量文獻中都會用到表達式這個關(guān)鍵詞來描述內(nèi)容。
排開這個原因,還有許多表達式是需要單獨學習的,如Cron表達式,正則表達式,對表達式的含義有所理解,就很容易接受類似的新名詞,理解他們?yōu)槭裁词潜磉_式。
JavaScript 中的表達式非常細,這些表達式可以組成一行行語句,這里例舉部分,方便讀者結(jié)合理解。
變量、關(guān)鍵字、字面量都屬于原始表達式。
var num=1;
num; // 變量 原始表達式
'123'; // 字符串字面量 原始表達式
this; // 關(guān)鍵字 原始表達式
代碼塊12345
這些原始表達式在程序運行過程中是不會報錯的,這也是最簡單的表達式。
原始表達式加上運算符就形成了復(fù)合表達式。
10 * 10; // 兩個數(shù)字字面量 使用乘號連接
代碼塊1
定義表達式及定義一個變量。
var person;
var func;
代碼塊123
初始化表達式與定義表達式不同,初始化表達式在定義變量的同時對變量做了初始化。
var number=10000;
var fn=function() {};
代碼塊12
除此之外還有非常非常多的表達式,通過這些簡單的表達式,我相信讀者對概念已經(jīng)有了一定的理解。
表達式的概念很廣泛,特別在數(shù)學領(lǐng)域更是常見。
在 JavaScript 中,基本所有的語句都能分解成表達式。
理解表達式的概念,可以更好的與他人交流,更容易的參閱文獻,更快速的理解相關(guān)內(nèi)容。
歡迎關(guān)注「慕課網(wǎng)」,發(fā)現(xiàn)更多IT圈優(yōu)質(zhì)內(nèi)容,分享干貨知識,幫助你成為更好的程序員!
擊右上方紅色按鈕關(guān)注“web秀”,讓你真正秀起來
作為一名程序猿,對正則表達式一定不會很陌生,但在平時開發(fā)中有時依然會遇到這樣或那樣的問題。本文從基礎(chǔ)出發(fā),本著讓初學者入門,高手溫故的初衷,相對系統(tǒng)性的介紹正了則相關(guān)知識。如有不準確的地方,歡迎吐槽
本文僅介紹 javascript 語言中的正則,其他語言雖有不同,但很類似,感興趣的自行g(shù)oogle吧。另外本文針對所有示例都給了輸出結(jié)果,希望讀者思考為什么返回這樣的結(jié)果,和自己期望的有什么不一樣,建議自己也動手輸入一下,加深記憶。
JavaScript正則表達式詳細總結(jié)
本文總體分兩部分:基礎(chǔ)知識 和 案例分析
一、正則申明方式
1、構(gòu)造函數(shù)方式
var reg=new RegExp('\d', 'gi');
JavaScript正則表達式詳細總結(jié)
說明:
'aBcd efg'.match(/[a-z]+/); // ["a"] 'aBcd efg'.match(/[a-z]+/i); // ["aBcd"] 'aBcd efg'.match(/[a-z]+/g); // ["a", "cd", "efg"] 'aBcd efg'.match(/[a-z]+/gi); // ["aBcd", "efg"] 'aB\ncd\n efg'.match(/^[a-z]+/m); // ["a"] 'aB\ncd\n efg'.match(/^[a-z]+/g); // ["a"] 'aB\ncd\n efg'.match(/^[a-z]+/gm); // ["a", "cd"] // 注意不是 ["a", "cd", "efg"]
具體用法請看下文相關(guān)的示例
2、字面量方式
相比較上一種方式,這一種更為常見,上面示例也都使用了這種方式
var reg=/\d/gi;
兩個斜線內(nèi)為正則的內(nèi)容,后面可以跟修飾符,與第一種構(gòu)造函數(shù)方式相比更簡潔,缺點是正則內(nèi)容不能拼接,對于大多數(shù)場景倆說足夠了
二、正則相關(guān)符號
1、方括號 [] 用法
用于查找方括號內(nèi)的任意字符:
JavaScript正則表達式詳細總結(jié)
注意:
1)^ 在 [] 內(nèi)開始位置及正則雙斜線開始位置有特殊含義,其他位置表示 ^ 字符本身
'adobe 2016'.match(/^[a-zA-Z]+/); // ["adobe"]
'adobe2016ps'.match(/\d+|^[a-z]+/g); // ["adobe", "2016"]
'adobe'.match(/[^abc]/g); // ["d", "o", "e"]
注: $ 與 ^ 的前兩個用法相似,只不過匹配的是以某某字符結(jié)尾的字符串,舉例:
'adobe 2016'.match(/\d+|[a-z]+$/g); // ["2016"] 'adobe'.match(/\d+|[a-z]+$/g); // ["adobe"]
2)- (連字符)表示左邊字符的 ASCII 值到右邊字符 ASCII 編碼值之間及左右字符自身的所有字符
'adobe PS 2016'.match(/[a-g]/g); // ["a", "d", "b", "e"]
3)- 連字符左側(cè)的字符對應(yīng)的 ASCII 值一定要小于或等于右側(cè)的字符,否則會報語法錯誤
'adobe'.match(/[z-a]/); // Uncaught SyntaxError: Invalid regular expression: /[z-a]/: Range out of order in character class...
4)如果希望對連字符 - 本身進行匹配,需要用反斜線轉(zhuǎn)義
'adobe-2016'.match(/[a-g\-]/g); // ["a", "d", "b", "e", "-"]
5)查看 ASCII 表就會發(fā)現(xiàn),大寫字母的 ASCII 值是小于小寫字母的,因此下面用法會報語法錯誤
'adobe-2016'.match(/[a-Z]/g); // Uncaught SyntaxError: Invalid regular expression: /[a-Z]/: Range out of order in character ...
那么問題來了,如果要表示所有字母,不區(qū)分大小寫怎么辦呢?其實有兩種方式:
A、第一種是使用修飾符 i,前面提到過。舉例:
'adobe-PS'.match(/[a-z]/gi); // ["a", "d", "o", "b", "e", "P", "S"]
B、第二種是在正則中明確指明大小寫字母,舉例:
'adobe-PS'.match(/[a-zA-Z]/g); // ["a", "d", "o", "b", "e", "P", "S"]
返回結(jié)果跟第一種一樣。當然這個例子有些特殊:匹配了所有大小寫字母。當只匹配部分大小寫字母的時候只能使用第二種方式,在此就不做示例了,讀者可以自己測試
6)匹配大小字母不能寫成 [A-z],雖然不會報語法錯誤,但隱式的放大了匹配范圍,查看 ASCII 會發(fā)現(xiàn),在大寫字母 Z 到小寫字母 a 之間還有 [、 \、 ]、 ^、 _、 ` 這6個字符,因此不能這么寫。
7)想必有同學會問, \w 不也可以匹配字母么?是的,\w 確實可以匹配字母,但跟上面說的一樣,也隱式的放大了匹配范圍,\w 除了匹配大小字母外還匹配了數(shù)字和下劃線,即 \w 與 [A-Za-z0-9_] 等價,當然 A-Z、a-z、0-9(等價于\d)、_這四組沒順序之分
2、特殊含義字符
'1+0.2*2=1.4'.match(/.{2}/g); // ["1+", "0.", "2*", "2=", "1."]
'ad34~!@$ps'.match(/\w/g); // ["a", "d", "3", "4", "p", "s"]
'ad34~!@$ps'.match(/\W/g); // ["~", "!", "@", "$"]
'ps6'.match(/\d/g); // ["6"]
'ps6'.match(/\D/g); // ["p", "s"]
'adobe ps'.match(/\s/g); // [" "]
'adobe ps'.match(/\S/g); // ["a", "d", "o", "b", "e", "p", "s"]
'adobe(2016) ps6.4'.match(/\b(\w+)/g); // ["adobe", "2016", "ps6", "4"]
'adobe(2016) ps6.4'.match(/\B(\w+)/g); // ["dobe", "016", "s6"]
'\0'.match(/\0/); // ["NUL"]
'adobe\nps'.match(/\n/).index; // 5
'adobe\fps'.match(/\f/).index; // 5
'adobe\rps'.match(/\r/).index; // 5
'adobe\tps'.match(/\t/).index; // 5
'adobe\vps'.match(/\v/).index; // 5
'a'.charCodeAt(0).toString(8); // "141" 'adobe ps'.match(/\141/g); // ["a"]
'a'.charCodeAt(0).toString(16); // "61" 'adobe ps'.match(/\x61/g); // ["a"]
'a'.charCodeAt(0).toString(16); // "61" 'adobe ps'.match(/\u0061/g); // ["a"]
注意:
window系統(tǒng)回車換行符為\r\n,linux系統(tǒng)下沒有\(zhòng)r,linux系統(tǒng)通過vi編輯器打開window系統(tǒng)的文本文件時候,經(jīng)常在行尾出現(xiàn)^M符號,也就是\r的原因,解析文本的時候需要注意相關(guān)判斷。
3、量詞說明
'adobe paas'.match(/a+\w+/g); // ["adobe", "aas"]
'ab3 aa12bb'.match(/a*\d+/g); // ["3", "aa12"]
'ab3 aa12bb'.match(/a?\d+/g); // ["3", "a12"]
'ab3 aa12bb aaa34'.match(/a{2}\d+/g); // ["aa12", "aa34"]
'a3 aaa12bb aaaaaaa34'.match(/a{2,4}\d+/g); // ["aaa12", "aaaa34"]
'a3 aaa12bbaa4'.match(/a{2,}\d+/g); // ["aaa12", "aa4"]
由上可知,以下 表達式1 與 表達式2 等價
JavaScript正則表達式詳細總結(jié)
4、符號說明
符號 {}、^、$、*、+、?、[]、[^]、- 已經(jīng)在前面介紹過,接下來看下其他特殊字符
'adobe ps13'.match(/([a-g]+l\d+)/g); // ["ad", "be", "13"]
'adobe'.match(/\w+/); // ["adobe"]
'a\\dobe'.match(/\\/); // ["\"]
5、小括號 () 用法
正則在非全局(g)模式下,通過match方式,返回的數(shù)組第一個值整體匹配的字符串,其他值為通過括號分組匹配到的
1)捕獲用法
'adobe cs9cs10, adobe cs11'.match(/([a-z]+\d+)+/); // ["cs9cs10", "cs10"] // 注意{2,}是對 括弧內(nèi)的匹配 的描述
"he is 12. she is 13. it's box".match(/(it|she|he)\s+is/g); // ["he is", "she is"]
'adobe cs9'.match(/[a-z]+\d+/); // ["cs9"] 'adobe cs9'.match(/[a-z]+(\d+)/); // ["cs9", "9"]
引用的結(jié)果可以通過 構(gòu)造函數(shù) RegExp 獲取,即 RegExp.一直到 RegExp.
'Can you can a can as a canner can can a can?'.match(/([cC]an+)\s+\1/g); // ["can can"] // 注意 `\1` 等價于正則里的 `([a-z]+)`,即與下面示例相同 'Can you can a can as a canner can can a can?'.match(/[cC]an+\s+[cC]an+/g); // ["can can"] // 如果把括弧去掉可以看下結(jié)果 'Can you can a can as a canner can can a can?'.match(/[cC]an+\s+\1/g); // null
2)非捕獲用法,以(?)形式出現(xiàn)
// 不使用括號時 'adobe12ps15test'.match(/[a-z]+\d+[a-z]+/); // ["adobe12ps"] // 使用括號分組 'adobe12ps15test'.match(/[a-z]+(\d+)([a-z]+)/); // ["adobe12ps", "12", "ps"] 'adobe12ps15test'.match(/[a-z]+(?:\d+)([a-z]+)/); // ["adobe12ps", "ps"] // 看起來上面語句不用(?:)也可以得到相同結(jié)果,即: 'adobe12ps15test'.match(/[a-z]+\d+([a-z]+)/); // ["adobe12ps", "ps"] // 注意,但需求希望匹配字母之間的規(guī)則復(fù)雜時,如希望匹配字母,且字母之間可以為1或3時,但不需要1和3 'adobe11ps15test'.match(/[a-z]+(1|3)+([a-z]+)/); // ["adobe11ps", "1", "ps"] // 返回中不希望包含數(shù)字怎么辦,可以使用非捕獲 'adobe11ps15test'.match(/[a-z]+(?:1|3)+([a-z]+)/); // ["adobe11ps", "ps"]
'adobe12ps15test'.match(/[a-z]+(?=\d)/g); // ["adobe", "ps"]
'adobe12ps15test'.match(/[a-z]+(?!\d)/g); // ["adob", "p", "test"]
'adobe12ps15test'.match(/(?<=\d)[a-z]+/g); // ["ps", "test"]
'adobe12ps15test'.match(/(?<!\d)[a-z]+/g); // ["adobe", "s", "est"]
3)注意
'11+2=13'.match(/\d+\+/g); // ["11+"] '(11+2)*2=26'.match(/\(\d+\+\d+\)/g); // ["(11+2)"]
// 注意下面兩個表達式返回的結(jié)果 'path C:\Windows\System32'.match(/([a-zA-Z]:\\\w+)/g); // null 'path C:\\Windows\\System32'.match(/([a-zA-Z]:\\\w+)/g); // ["C:\Windows"]
說明:
在申明字符串 'path C:\Windows\System32' 時,其中的 '' 就已經(jīng)被當做轉(zhuǎn)移符,既是 '\W'==='W',所以如果希望申明的字符串中包含反斜線,需要在加一個反斜線轉(zhuǎn)義,即 \
6、正則相關(guān)方法
1) RegExp對象相關(guān)方法
JavaScript正則表達式詳細總結(jié)
2)String對象相關(guān)方法
JavaScript正則表達式詳細總結(jié)
3)replace 具體用法
顧名思義,是字符串替換方法,但用法比較廣泛,相信讀者已經(jīng)非常熟悉了。在此就當復(fù)習了
A、 基本用法
直接傳入字符串進行替換,找到子串后只替換一次,舉例:
'adobe abc'.replace('b', '_') // "ado_e abc" // 注意 第二個 b 沒有被替換
如果希望全部替換,可以使用正則表達式并用全局修飾符 g 方式,舉例:
'adobe abc'.replace(/b/g, '_') // "ado_e a_c"
B、 高級用法
第二個參數(shù)可以使用 function,其中有三個參數(shù),分別為 匹配的字符串、當前匹配的字符串index值、匹配的源字符串,最終結(jié)果根據(jù)每次匹配結(jié)果進行相應(yīng)的替換
舉例:
'adobe aacc bbaa'.replace(/a+/g, function(str, index, source){ if(index > 0){ return str.toUpperCase(); } else { return str; } }); // "adobe AAcc bbAA"
一、常見匹配
在寫正則之前,需要注意以下幾點:
1、手機號
規(guī)則:以1開頭第二位為3、5、7、8且長度為11位的數(shù)字組合
/^1[3578]\d{9}$/.test(13600001111); // true
2、 字符串提取
舉例:提取字符串中的數(shù)字
分析:
根據(jù)對數(shù)字的理解,可能為負數(shù),即-?,如果是負數(shù),其后需要是數(shù)字且至少一位,即 -?\d+,小數(shù)部分可能有也可能沒有,所以需要對小數(shù)部分括弧起來用 ? 或 {0, 1}限定,因為.是特殊字符需要轉(zhuǎn)義,于是表達式為:-?\d+(\.\d+)?
'(12.3 - 32.3)*2=-40'.match(/-?\d+(\.\d+)?/g); // ["12.3", "32.3", "2", "-40"]
二、jQuery中的正則片段
1、表達式
在jQuery 3.1.2-pre中找到一個解析單標簽的正則,如下:
/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i
2、分解
乍一看有點懵,其實拆解之后就容易理解了,注意拆解的步驟,通常來說:
1) 第一步可以先看括號 () ,可以將各個小括號及非括號的分成不同部分,如
/^< ([a-z][^\/\0>:\x20\t\r\n\f]*) [\x20\t\r\n\f]*\/?> (?:<\/\1>|) $/i
2) 第二步可以將中括號分開
/^< ( [a-z] [^\/\0>:\x20\t\r\n\f]* ) [\x20\t\r\n\f]* \/?> (?:<\/\1>|) $/i
現(xiàn)在是不是已經(jīng)很清楚了,接下來分解下,就很容易理解了
3、詳解
喜歡小編的點擊關(guān)注,了解更多知識!
正則表達式(英語:Regular Expression,在代碼中常簡寫為regex、regexp或RE)使用單個字符串來描述、匹配一系列符合某個句法規(guī)則的字符串搜索模式。
搜索模式可用于文本搜索和文本替換。
什么是正則表達式?
正則表達式是由一個字符序列形成的搜索模式。
當你在文本中搜索數(shù)據(jù)時,你可以用搜索模式來描述你要查詢的內(nèi)容。
正則表達式可以是一個簡單的字符,或一個更復(fù)雜的模式。
正則表達式可用于所有文本搜索和文本替換的操作。
語法
/pattern/modifiers;
實例:
var patt=/w3cschool/i
實例解析:
/w3cschool/i 是一個正則表達式。
w3cschool 是一個模式 (用于檢索)。
i 是一個修飾符 (搜索不區(qū)分大小寫)。
使用字符串方法
在 JavaScript 中,正則表達式通常用于兩個字符串方法 : search() 和 replace()。
search() 方法 用于檢索字符串中指定的子字符串,或檢索與正則表達式相匹配的子字符串,并返回子串的起始位置。
replace() 方法 用于在字符串中用一些字符替換另一些字符,或替換一個與正則表達式匹配的子串。
search() 方法使用正則表達式
實例
使用正則表達式搜索 "w3cschool" 字符串,且不區(qū)分大小寫:
var str="Visit w3cschool";
var n=str.search(/w3cschool/i);
輸出結(jié)果為:
6
search() 方法使用字符串
search 方法可使用字符串作為參數(shù)。字符串參數(shù)會轉(zhuǎn)換為正則表達式:
實例
檢索字符串中 "w3cschool" 的子串:
var str="Visit w3cschool!";
var n=str.search("w3cschool");
replace() 方法使用正則表達式
實例
使用正則表達式且不區(qū)分大小寫將字符串中的 Microsoft 替換為 w3cschool :
varstr="Visit Microsoft!";
var res=str.replace(/microsoft/i, "w3cschool");
結(jié)果輸出為:
Visit w3cschool!
replace() 方法使用字符串
replace() 方法將接收字符串作為參數(shù):
var str="Visit Microsoft!";
var res=str.replace("Microsoft", "w3cschool");
你注意到了嗎?
正則表達式參數(shù)可用在以上方法中 (替代字符串參數(shù))。正則表達式使得搜索功能更加強大(如實例中不區(qū)分大小寫)。 |
正則表達式修飾符
修飾符 可以在全局搜索中不區(qū)分大小寫:
修飾符 | 描述 |
---|---|
i | 執(zhí)行對大小寫不敏感的匹配。 |
g | 執(zhí)行全局匹配(查找所有匹配而非在找到第一個匹配后停止)。 |
m | 執(zhí)行多行匹配。 |
正則表達式模式
方括號用于查找某個范圍內(nèi)的字符:
表達式 | 描述 |
---|---|
[abc] | 查找方括號之間的任何字符。 |
[0-9] | 查找任何從 0 至 9 的數(shù)字。 |
(x|y) | 查找任何以 | 分隔的選項。 |
元字符是擁有特殊含義的字符:
元字符 | 描述 |
---|---|
\d | 查找數(shù)字。 |
\s | 查找空白字符。 |
\b | 匹配單詞邊界。 |
\uxxxx | 查找以十六進制數(shù) xxxx 規(guī)定的 Unicode 字符。 |
量詞:
量詞 | 描述 |
---|---|
n+ | 匹配任何包含至少一個 n 的字符串。 |
n* | 匹配任何包含零個或多個 n 的字符串。 |
n? | 匹配任何包含零個或一個 n 的字符串。 |
使用 RegExp 對象
在 JavaScript 中,RegExp 對象是一個預(yù)定義了屬性和方法的正則表達式對象。
使用 test()
test() 方法是一個正則表達式方法。
test() 方法用于檢測一個字符串是否匹配某個模式,如果字符串中含有匹配的文本,則返回 true,否則返回 false。
以下實例用于搜索字符串中的字符 "e":
實例
var patt=/e/;
patt.test("The best things in life are free!");
字符串中含有 "e",所以該實例輸出為:
true
你可以不用設(shè)置正則表達式的變量,以上兩行代碼可以合并為一行:
/e/.test("The best things in life are free!")
使用 exec()
exec() 方法是一個正則表達式方法。
exec() 方法用于檢索字符串中的正則表達式的匹配。
該函數(shù)返回一個數(shù)組,其中存放匹配的結(jié)果。如果未找到匹配,則返回值為 null。
以下實例用于搜索字符串中的字母 "e":
Example 1
/e/.exec("The best things in life are free!");
字符串中含有 "e",所以該實例輸出為:
e
完整的 RegExp 參考手冊
完整的 RegExp 對象參考手冊,請參考我們的 JavaScript RegExp 參考手冊。
該參考手冊包含了所有 RegExp 對象的方法和屬性。
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。