整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          JavaScript正則表達式常用技巧

          則表達式是用于匹配字符串中字符組合的模式。在 JavaScript 中,正則表達式也是對象。這些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、matchAll、replace、search 和 split 方法。正則表達式的掌握程度能粗略地看出程序員的技術底子,所以技術面試、編程競賽等 都特別喜歡考察正則表達式。本篇就帶你一起夯實一下 JavaScript 正則表達式的一些使用技巧:

          創建正則表達式

          在 JavaScript 的世界,創建正則表達式有2個方法: (1)使用一個正則表達式字面量,其由包含在斜杠之間的模式組成。比如 :

          const reg = /ab+c/
          

          (2)調用RegExp對象的構造函數。比如:

          const reg = new RegExp("ab+c")
          

          注意:以上2個方法雖然都能創建正則表達式,但是還是有區別的: (1)使用第一個方法,在腳本加載后正則表達式字面量就會被編譯。當正則表達式保持不變時,使用此方法可獲得更好的性能。 (2)使用第二個方法,在腳本運行過程中用構造函數創建的正則表達式會被編譯。如果正則表達式將會改變,或者它將會從用戶輸入等來源中動態地產生,就需要使用構造函數來創建正則表達式。

          當然,這樣表述可能不太深刻,下面找一道面試題帶你實踐一下。

          經典面試題 "Word Finder"

          題目要求:
          使用一個方法來擴展字典,該方法返回與模式匹配的單詞列表。這個模式可以包含字母(小寫)和占位符("?")。占位符只代表一個任意的字母,比如: 
          
          const fruits = new Dictionary(['banana', 'apple', 'papaya', 'cherry']);
          fruits.getMatchingWords('lemon');     // must return []
          fruits.getMatchingWords('cherr??');   // must return []
          fruits.getMatchingWords('?a?a?a');    // must return ['banana', 'papaya']
          fruits.getMatchingWords('??????');    // must return ['banana', 'papaya', 'cherry']
          
          補充說明:
          (1)單詞和模式都是小寫
          (2)返回單詞的順序無關緊要
          

          上面這道題目是典型的 正則表達式應用題,考察的知識點是2個: (1)使用 RegExp 對象 動態創建正則表達式 (2)使用 /./ 匹配一個任意字符

          因此不難有如下解決方案(ps:這個是我的解決方案,雖然解法比較low,但是邏輯應該還算清晰,容易理解)

          // 字典構造器
          function Dictionary(words) {
            this.words = words;
          }
          
          // 原型里拓展解法
          Dictionary.prototype.getMatchingWords = function(pattern) {
            let res = []
            const reg = new RegExp("^" + pattern.replace(/\?/g, '.') + "$")  // 創建正則表達式
            for (let x of this.words) {
              if (reg.test(x)) res.push(x) 
            }
            return res
          }
          

          如果你有更好的解法,歡迎評論留言哈 ^_^

          正則表達式模式

          一個正則表達式模式是由簡單的字符所構成的,比如 /abc/;或者是簡單和特殊字符的組合,比如 /ab*c/ 或 /Chapter (\d+)\.\d*/

          簡單模式

          簡單模式是由想要匹配的具體字符組成,且嚴格匹配字符順序。比如,/abc/ 這個模式就能且僅能匹配 "abc" 字符按照順序同時出現的情況,而 "bac" 或 "cab" 等就無法匹配。

          特殊字符

          當需要匹配一個不確定的字符串時,比如尋找一個或多個 "b",或者尋找空格,可以在模式中使用特殊字符。特殊字符還包括如下:

          • 斷言:表示一個匹配在某些條件下發生。斷言包括先行斷言、后行斷言和條件表達式
          • 字符類:區分不同類型的字符,例如區分字母和數字
          • 組和范圍:表示表達式字符的分組和范圍
          • 量詞:表示匹配的字符或條件表達式的數量
          • Unicode屬性轉義:基于 Unicode字符屬性區分字符,例如大寫和小寫字母、數字符合和標點

          Escaping

          當需要使用任何特殊字符的字面值(例如,搜索字符 *),你必須通過在它前面放一個反斜杠來轉義它。 例如,要搜索'a'后跟*后跟'b',你應該使用 /a\*b/- 反斜杠“轉義”字符 *,使其成為文字而非特殊符號。將用戶輸入轉義為正則表達式中的一個字面字符串,可以通過簡單的替換來實現:

          function escapeRegExp(string) {
            return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");   //$&表示整個被匹配的字符串
          }
          

          使用正則表達式

          前面講到,正則表達式可以被用于 RegExp 的 exec 和 test 方法以及 String 的 match、replace、search 和 split 方法。這些方法在 JavaScript 手冊 中有詳細的解釋,下面只簡單羅列下各自功能,不做展開:

          • exec:在字符串中執行查找匹配的 RegExp 方法,它返回一個數組(未匹配到則返回 null)
          • test:在字符串中測試是否匹配的 RegExp 方法,它返回 true 或 false
          • match:在字符串中執行查找匹配的 String 方法,它返回一個數組,在未匹配到時會返回 null
          • matchAll:在字符串中執行查找所有匹配的 String 方法,它返回一個迭代器(iterator)
          • search:在字符串中測試匹配的 String 方法,它返回匹配到的位置索引,或者在失敗時返回 -1
          • replace:在字符串中執行查找匹配的 String 方法,并且使用替換字符串替換掉匹配到的子字符串
          • split:使用正則表達式或者一個固定字符串分隔一個字符串的String方法,并將分隔后的子字符串存儲到數組中

          一個簡單的快速記憶方法: (1)想要知道在一個字符串中的一個匹配是否被找到,使用 test 或 search 方法 (2)想得到更多的信息(但是比較慢)則可以使用 exec 或 match 方法

          舉個栗子,使用exec方法在一個字符串中查找一個匹配:

          const myRe = /d(b+)d/g;
          const myArray = myRe.exec("cdbbdbsbz");
          

          如果不需要訪問正則表達式的屬性,這個腳本通過另一個方法來創建myArray:

          const myArray = /d(b+)d/g.exec("cdbbdbsbz");
          // 和 "cdbbdbsbz".match(/d(b+)d/g); 相似。
          // 但是 "cdbbdbsbz".match(/d(b+)d/g) 輸出數組 [ "dbbd" ],
          // 而 /d(b+)d/g.exec('cdbbdbsbz') 輸出數組 [ "dbbd", "bb", index: 1, input: "cdbbdbsbz" ].
          

          如果想通過一個字符串構建正則表達式,那么這個腳本還有另一種方法:

          const myRe = new RegExp("d(b+)d", "g");
          const myArray = myRe.exec("cdbbdbsbz");
          

          使用括號的子字符串匹配

          一個正則表達式模式使用括號,將導致相應的子匹配被記住。例如,/a(b)c / 可以匹配字符串“abc”,并且記得“b”。回調這些括號中匹配的子串,使用數組元素[1],……[n]。

          使用括號匹配的子字符串的數量是無限的。返回的數組中保存所有被發現的子匹配。下面的例子說明了如何使用括號的子字符串匹配。

          下面的腳本使用 replace() 方法來轉換字符串中的單詞。在匹配到的替換文本中,腳本使用替代的, 表示第一個和第二個括號的子字符串匹配:

          const re = /(\w+)\s(\w+)/;
          const str = "John Smith";
          const newstr = str.replace(re, "$2, $1");
          console.log(newstr);   // 輸出 "Smith, John"
          

          通過標志進行高級搜索

          正則表達式有六個可選參數 (flags) 允許全局和不分大小寫搜索等。這些參數既可以單獨使用也能以任意順序一起使用, 并且被包含在正則表達式實例中:

          • g:全局搜索
          • i:不區分大小寫搜索
          • m: 多行搜索
          • s:允許.匹配換行符
          • u:使用Unicode碼的模式進行匹配
          • y:執行“粘性(sticky)”搜索, 匹配從目標字符串的當前位置開始

          例如,re = /\w+\s/g 將創建一個查找一個或多個字符后有一個空格的正則表達式,或者組合起來像此要求的字符串:

          const re = /\w+\s/g;
          const str = "fee fi fo fum";
          const myArray = str.match(re);
          console.log(myArray);
          
          // ["fee ", "fi ", "fo "]
          

          使用 .exec() 方法時,與 g 標志關聯的行為是不同的。 (“class”和“argument”的作用相反:在.match()的情況下,字符串類(或數據類型)擁有該方法,而正則表達式只是一個參數,而在.exec()的情況下,它是擁有該方法的正則表達式,其中字符串是參數。對比str.match(re)與re.exec(str) ), g標志與.exec()方法一起使用獲得迭代進展:

          const xArray; while(xArray = re.exec(str)) console.log(xArray);
          // produces: 
          // ["fee ", index: 0, input: "fee fi fo fum"]
          // ["fi ", index: 4, input: "fee fi fo fum"]
          // ["fo ", index: 7, input: "fee fi fo fum"]
          

          除此之外,m標志用于指定多行輸入字符串應該被視為多個行。如果使用m標志,^和$匹配的開始或結束輸入字符串中的每一行,而不是整個字符串的開始或結束。


          @參考:正則表達式

          、校驗數字的表達式

          1. 數字:^[0-9]*$
          2. n位的數字:^\d{n}$
          3. 至少n位的數字:^\d{n,}$
          4. m-n位的數字:^\d{m,n}$
          5. 零和非零開頭的數字:^(0|[1-9][0-9]*)$
          6. 非零開頭的最多帶兩位小數的數字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
          7. 帶1-2位小數的正數或負數:^(\-)?\d+(\.\d{1,2})?$
          8. 正數、負數、和小數:^(\-|\+)?\d+(\.\d+)?$
          9. 有兩位小數的正實數:^[0-9]+(.[0-9]{2})?$
          10. 有1~3位小數的正實數:^[0-9]+(.[0-9]{1,3})?$
          11. 非零的正整數:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
          12. 非零的負整數:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
          13. 非負整數:^\d+$ 或 ^[1-9]\d*|0$
          14. 非正整數:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
          15. 非負浮點數:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
          16. 非正浮點數:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
          17. 正浮點數:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
          18. 負浮點數:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
          19. 浮點數:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

          二、校驗字符的表達式

          1. 漢字:^[\u4e00-\u9fa5]{0,}$
          2. 英文和數字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
          3. 長度為3-20的所有字符:^.{3,20}$
          4. 由26個英文字母組成的字符串:^[A-Za-z]+$
          5. 由26個大寫英文字母組成的字符串:^[A-Z]+$
          6. 由26個小寫英文字母組成的字符串:^[a-z]+$
          7. 由數字和26個英文字母組成的字符串:^[A-Za-z0-9]+$
          8. 由數字、26個英文字母或者下劃線組成的字符串:^\w+$ 或 ^\w{3,20}
          9. 中文、英文、數字包括下劃線:^[\u4E00-\u9FA5A-Za-z0-9_]+$
          10. 中文、英文、數字但不包括下劃線等符號:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
          11. 可以輸入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+
          12. 禁止輸入含有~的字符[^~\x22]+

          其它:

          .*匹配除 \n 以外的任何字符。

          /[\u4E00-\u9FA5]/ 漢字

          /[\uFF00-\uFFFF]/ 全角符號

          /[\u0000-\u00FF]/ 半角符號

          三、特殊需求表達式

          1. Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
          2. 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
          3. InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
          4. 手機號碼:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
          5. 電話號碼("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
          6. 國內電話號碼(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
          7. 身份證號(15位、18位數字):^\d{15}|\d{18}$
          8. 短身份證號碼(數字、字母x結尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
          9. 帳號是否合法(字母開頭,允許5-16字節,允許字母數字下劃線):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
          10. 密碼(以字母開頭,長度在6~18之間,只能包含字母、數字和下劃線):^[a-zA-Z]\w{5,17}$
          11. 強密碼(必須包含大小寫字母和數字的組合,不能使用特殊字符,長度在8-10之間):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
          12. 日期格式:^\d{4}-\d{1,2}-\d{1,2}
          13. 一年的12個月(01~09和1~12):^(0?[1-9]|1[0-2])$
          14. 一個月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$

          錢的輸入格式:

          1.有四種錢的表示形式我們可以接受:"10000.00" 和 "10,000.00", 和沒有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$

          2.這表示任意一個不以0開頭的數字,但是,這也意味著一個字符"0"不通過,所以我們采用下面的形式:^(0|[1-9][0-9]*)$

          3.一個0或者一個不以0開頭的數字.我們還可以允許開頭有一個負號:^(0|-?[1-9][0-9]*)$

          4.這表示一個0或者一個可能為負的開頭不為0的數字.讓用戶以0開頭好了.把負號的也去掉,因為錢總不能是負的吧.下面我們要加的是說明可能的小數部分:^[0-9]+(.[0-9]+)?$

          5.必須說明的是,小數點后面至少應該有1位數,所以"10."是不通過的,但是 "10" 和 "10.2" 是通過的:^[0-9]+(.[0-9]{2})?$

          6.這樣我們規定小數點后面必須有兩位,如果你認為太苛刻了,可以這樣:^[0-9]+(.[0-9]{1,2})?$

          7.這樣就允許用戶只寫一位小數.下面我們該考慮數字中的逗號了,我們可以這樣:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$

          8.1到3個數字,后面跟著任意個 逗號+3個數字,逗號成為可選,而不是必須:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$

          備注:這就是最終結果了,別忘了+可以用*替代如果你覺得空字符串也可以接受的話(奇怪,為什么?)最后,別忘了在用函數時去掉去掉那個反斜杠,一般的錯誤都在這里

          1. xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\.[x|X][m|M][l|L]$
          2. 中文字符的正則表達式:[\u4e00-\u9fa5]
          3. 雙字節字符:[^\x00-\xff] (包括漢字在內,可以用來計算字符串的長度(一個雙字節字符長度計2,ASCII字符計1))
          4. 空白行的正則表達式:\n\s*\r (可以用來刪除空白行)
          5. HTML標記的正則表達式:<(\S*?)[^>]*>.*?</>|<.*? /> (網上流傳的版本太糟糕,上面這個也僅僅能部分,對于復雜的嵌套標記依舊無能為力)
          6. 首尾空白字符的正則表達式:^\s*|\s*$或(^\s*)|(\s*$) (可以用來刪除行首行尾的空白字符(包括空格、制表符、換頁符等等),非常有用的表達式)
          7. 騰訊QQ號:[1-9][0-9]{4,} (騰訊QQ號從10000開始)
          8. 中國郵政編碼:[1-9]\d{5}(?!\d) (中國郵政編碼為6位數字)
          9. IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址時有用)
          10. IP地址:((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))
          11. IP-v4地址:\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b (提取IP地址時有用)
          12. 校驗IP-v6地址:(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))
          13. 子網掩碼:((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))
          14. 校驗日期:^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$(“yyyy-mm-dd“ 格式的日期校驗,已考慮平閏年。)
          15. 抽取注釋:<!--(.*?)-->
          16. 查找CSS屬性:^\s*[a-zA-Z\-]+\s*[:]{1}\s[a-zA-Z0-9\s.#]+[;]{1}
          17. 提取頁面超鏈接:(<a\s*(?!.*\brel=)[^>]*)(href="https?:\/\/)((?!(?:(?:www\.)?'.implode('|(?:www\.)?', $follow_list).'))[^" rel="external nofollow" ]+)"((?!.*\brel=)[^>]*)(?:[^>]*)>
          18. 提取網頁圖片:\< *[img][^\\>]*[src] *= *[\"\']{0,1}([^\"\'\ >]*)
          19. 提取網頁顏色代碼:^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$
          20. 文件擴展名效驗:^([a-zA-Z]\:|\\)\\([^\\]+\\)*[^\/:*?"<>|]+\.txt(l)?$
          21. 判斷IE版本:^.*MSIE [5-8](?:\.[0-9]+)?(?!.*Trident\/[5-9]\.0).*$

          附表:

          Java中,可以使用正則表達式來提取HTML中的任意內容。以下是一個示例代碼,演示如何使用正則表達式從HTML中提取文本:

          import java.util.regex.Matcher;  import java.util.regex.Pattern;    public class HtmlParser {      public static void main(String[] args) {          String html = "<html><head><title>My Website</title></head><body><p>This is some sample text.</p></body></html>";          Pattern pattern = Pattern.compile("<p[^>]*>(.*?)</p>");          Matcher matcher = pattern.matcher(html);          String pText = matcher.group(1);          System.out.println(pText);      }  }

          在上面的代碼中,我們首先定義了一個HTML字符串,然后使用PatternMatcher類來匹配HTML中的文本。Pattern類用于定義正則表達式,Matcher類用于在HTML中查找匹配的文本。

          在正則表達式中,我們使用了<p[^>]*>來匹配以<p>開頭,后面跟著任意數量的字符,再以</p>結尾的文本。其中,[^>]*表示匹配任意數量的字符,</p>表示匹配</p>后面的任意字符。

          最后,我們使用group(1)方法來獲取匹配的文本,并將其打印到控制臺上。

          需要注意的是,正則表達式可以根據HTML標簽的不同來進行不同的


          主站蜘蛛池模板: 亚洲日韩一区精品射精| 国产在线一区二区在线视频| 亚洲视频一区在线观看| 亚洲AV美女一区二区三区| 日韩人妻无码一区二区三区久久 | 日韩精品福利视频一区二区三区| 麻豆高清免费国产一区| 亚洲.国产.欧美一区二区三区| 国内精品视频一区二区八戒| 欲色影视天天一区二区三区色香欲 | 国产成人精品一区二区秒拍 | 成人在线观看一区| 日本一区二区三区中文字幕| 中文字幕一区二区三区精华液| 亚洲国产精品一区二区成人片国内 | 国产SUV精品一区二区四| 免费在线观看一区| 日本在线一区二区| 日韩一区二区在线免费观看| 中文字幕一区二区三区永久 | 无码中文人妻在线一区二区三区| 国产福利一区视频| 久久久久99人妻一区二区三区| 国产伦精品一区二区三区不卡| 精品视频一区二区三区四区五区| 日本免费一区二区在线观看| 福利一区国产原创多挂探花| 亚洲综合色一区二区三区小说| 无码8090精品久久一区| 精品一区二区三区在线观看视频| 成人免费视频一区| 亚欧成人中文字幕一区| 国产精品区一区二区三| 91在线看片一区国产| 国产一区二区精品在线观看| 中文字幕在线一区二区在线| 亚洲AV无码一区二三区| 亚洲变态另类一区二区三区| 亚洲AV无码一区二区二三区入口| 国产亚洲福利精品一区二区| AV鲁丝一区鲁丝二区鲁丝三区|