摘要:正則大法好,正則大法好,正則大法好,重要的事情說三遍。第二部分,這個部分是整個表達式的關鍵部分。學習正則如果還沒有系統學習正則表達式,這里提供一些網上經典的教程供大家學習。正則表達式使用單個字符串來描述匹配一系列匹配某個句法規則的字符串。
原文收錄在我的 GitHub博客 (https://github.com/jawil/blog) ,喜歡的可以關注最新動態,大家一起多交流學習,共同進步,以學習者的身份寫博客,記錄點滴。
有些童鞋肯定有所疑惑,花了大量時間學習正則表達式,卻發現沒有用武之地,正則不就是驗證個郵箱嘛,其他地方基本用不上,其實,大部分人都是這種感覺,所以有些人干脆不學,覺得又難又沒多大用處。殊不知,想要成為編程大牛,正則表達式必須玩轉,GitHub上優秀的開源庫和框架里面到處都是強大的正則匹配,當年jQuery作者也被稱為正則小王子。這里分享一些工作中用到的和自己收集的一些正則表達式的妙用,到處閃耀著開發者智慧的火花。
實現一個需求的方法很多種,哪種更好,仁者見仁智者見智,這里只提供一種對比的思維來激發大家學習正則的興趣和養成活用正則的思維。
作為前端開發人員,總會有點自己的奇技淫巧,畢竟前端開發不同于后端,代碼全部暴漏給用戶不說,代碼冗余了少則影響帶寬,多則效率降低。正則表達式(Regular Expression),這是一塊硬骨頭,很難啃,但是啃著又很香。所以今天我也來爆一些正則表達式的奇技淫巧。
正則大法好,正則大法好,正則大法好,重要的事情說三遍。
1、獲取鏈接 https://www.baidu.com?name=jawil&age=23 name的value值非正則實現:
function getParamName(attr) { let search = window.location.search // "?name=jawil&age=23" let param_str = search.split("?")[1] // "name=jawil&age=23" let param_arr = param_str.split("&") // ["name=jawil", "age=23"] let filter_arr = param_arr.filter(ele => { // ["name=jawil"] return ele.split("=")[0] === attr }) return decodeURIComponent(filter_arr[0].split("=")[1]) } console.log(getParamName("name")) // "jawil"
用正則實現:
function getParamName(attr) { let match = RegExp(`[?&]${attr}=([^&]*)`) //分組運算符是為了把結果存到exec函數返回的結果里 .exec(window.location.search) //["?name=jawil", "jawil", index: 0, input: "?name=jawil&age=23"] return match && decodeURIComponent(match[1].replace(/+/g, " ")) // url中+號表示空格,要替換掉 } console.log(getParamName("name")) // "jawil"
看不太懂先學習一下這篇文章:[[ JS 進階 ] test, exec, match, replace](https://segmentfault.com/a/11...
2、 數字格式化問題,1234567890 --> 1,234,567,890非正則實現:
let test = "1234567890" function formatCash(str) { let arr = [] for (let i = 1; i < str.length; i++) { if (str.length % 3 && i == 1) arr.push(str.substr(0, str.length % 3)) if (i % 3 === 0) arr.push(str.substr(i - 2, 3)) } return arr.join(",") } console.log(formatCash(test)) // 1,234,567,890
用正則實現:
let test1 = "1234567890" let format = test1.replace(/B(?=(d{3})+(?!d))/g, ",") console.log(format) // 1,234,567,890
下面簡單分析下正則/B(?=(d{3})+(?!d))/g:
/B(?=(d{3})+(?!d))/g:正則匹配邊界B,邊界后面必須跟著(d{3})+(?!d);
(d{3})+:必須是1個或多個的3個連續數字;
(?!d):第2步中的3個數字不允許后面跟著數字;
(d{3})+(?!d):所以匹配的邊界后面必須跟著3*n(n>=1)的數字。
最終把匹配到的所有邊界換成,即可達成目標。
3、去掉字符串左右兩邊的空格," jaw il " --> “jaw il”非正則實現:
function trim(str) { let start, end for (let i = 0; i < str.length; i++) { if (str[i] !== " ") { start = i break } } for (let i = str.length - 1; i > 0; i--) { if (str[i] !== " ") { end = i break } } return str.substring(start, end - 1) } let str = " jaw il " console.log(trim(str)) // "jaw il"
用正則實現:
function trim(str) { return str.replace(/(^s*)|(s*$)/g, "") } let str = " jaw il " console.log(trim(str)) // "jaw il"4、判斷一個數是否是質數 3 --> true
質數又稱素數。指在一個大于1的自然數中,除了1和此整數自身外,沒法被其他自然數整除的數。
非正則實現:
function isPrime(num){ // 不是數字或者數字小于2 if(typeof num !== "number" || !Number.isInteger(num)){ // Number.isInterget 判斷是否為整數 return false } //2是質數 if(num == 2){ return true }else if(num % 2 == 0){ //排除偶數 return false } //依次判斷是否能被奇數整除,最大循環為數值的開方 let squareRoot = Math.sqrt(num) //因為2已經驗證過,所以從3開始;且已經排除偶數,所以每次加2 for(let i = 3; i <= squareRoot; i += 2) { if (num % i === 0) { return false } } return true } console.log(isPrime(19)) // true
用正則實現:
function isPrime(num) { return !/^1?$|^(11+?)1+$/.test(Array(num+1).join("1")) } console.log(isPrime(19)) // true
要使用這個正規則表達式,你需要把自然數轉成多個1的字符串,如:2 要寫成 “11”, 3 要寫成 “111”, 17 要寫成“11111111111111111”,這種工作使用一些腳本語言可以輕松的完成,JS實現也很簡單,我用Array(num+1).join("1")這種方式實現了一下。
一開始我對這個表達式持懷疑態度,但仔細研究了一下這個表達式,發現是非常合理的,下面,讓我帶你來細細剖析一下是這個表達式的工作原理。
首先,我們看到這個表達式中有“|”,也就是說這個表達式可以分成兩個部分:/^1?$/ 和 /^(11+?)1+$/
第一部分:/^1?$/, 這個部分相信不用我多說了,其表示匹配“空串”以及字串中只有一個“1”的字符串。
第二部分:/^(11+?)1+$/ ,這個部分是整個表達式的關鍵部分。其可以分成兩個部分,(11+?)?和 1+$ ,前半部很簡單了,匹配以“11”開頭的并重復0或n個1的字符串,后面的部分意思是把前半部分作為一個字串去匹配還剩下的字符串1次或多次(這句話的意思是——剩余的字串的1的個數要是前面字串1個數的整數倍)。
可見這個正規則表達式是取非素數,要得到素數還得要對整個表達式求反。通過上面的分析,我們知道,第二部分是最重要的,對于第二部分,舉幾個例子,
示例一:判斷自然數8。我們可以知道,8轉成我們的格式就是“11111111”,對于 (11+?) ,其匹配了“11”,于是還剩下“111111”,而 1+$ 正好匹配了剩下的“111111”,因為,“11”這個模式在“111111”出現了三次,符合模式匹配,返回true。所以,匹配成功,于是這個數不是質數。
示例二:判斷自然數11。轉成我們需要的格式是“11111111111”(11個1),對于 (11+?) ,其匹配了“11”(前兩個1),還剩下“111111111”(九個1),而 1+$ 無法為“11”匹配那“九個1”,因為“11”這個模式并沒有在“九個1”這個串中正好出現N次。于是,我們的正則表達式引擎會嘗試下一種方法,先匹配“111”(前三個1),然后把“111”作為模式去匹配剩下的“11111111”(八個1),很明顯,那“八個1”并沒有匹配“三個1”多次。所以,引擎會繼續向下嘗試……直至嘗試所有可能都無法匹配成功。所以11是素數。
通過示例二,我們可以得到這樣的等價數算算法,正則表達式會匹配這若干個1中有沒有出現“二個1”的整數倍,“三個1”的整數倍,“四個1”的整數倍……,而,這正好是我們需要的算素數的算法。現在大家明白了吧。
5、字符串數組去重 ["a","b","c","a","b","c"] --> ["a","b","c"]這里只考慮最簡單字符串的數組去重,暫不考慮,對象,函數,NaN等情況,這種用正則實現起來就吃力不討好了。
非正則實現:
①ES6實現
let str_arr=["a","b","c","a","b","c"] function unique(arr){ return [...new Set(arr)] } console.log(unique(str_arr)) // ["a","b","c"]
②ES5實現
var str_arr = ["a", "b", "c", "a", "b", "c"] function unique(arr) { return arr.filter(function(ele, index, array) { return array.indexOf(ele) === index }) } console.log(unique(str_arr)) // ["a","b","c"]
③ES3實現
var str_arr = ["a", "b", "c", "a", "b", "c"] function unique(arr) { var obj = {}, array = [] for (var i = 0, len = arr.length; i < len; i++) { var key = arr[i] + typeof arr[i] if (!obj[key]) { obj[key] = true array.push(arr[i]) } } return array } console.log(unique(str_arr)) // ["a","b","c"]
額,ES4呢。。。對不起,由于歷史原因,ES4改動太大,所以被廢棄了。
可以看到從ES3到ES6,代碼越來越簡潔,JavaScript也越來越強大。
用正則實現:
var str_arr = ["a", "b", "c", "a", "b", "c"] function unique(arr) { return arr.sort().join(",,"). replace(/(,|^)([^,]+)(,,2)+(,|$)/g, "$1$2$4"). replace(/,,+/g, ","). replace(/,$/, ""). split(",") } console.log(unique(str_arr)) // ["a","b","c"]
這里我只是拋磚引玉的利用幾個例子對比來展現正則表達式的強大,其實正則表達式的應用遠遠不止這些,這里列出的只是冰山一角,更多的奇淫技巧需要你們來創造,知識點API是有限的,技巧和創造卻是無限的,歡迎大家開動腦門,創造或分享自己的奇淫技巧。
學習正則如果還沒有系統學習正則表達式,這里提供一些網上經典的教程供大家學習。
正則表達式(Regular Expression),這是一塊硬骨頭,很難啃,但是啃著又很香。
正則表達式使用單個字符串來描述、匹配一系列匹配某個句法規則的字符串。很多地方我們都需要使用正則,所以今天就將一些優秀的教程,工具總結起來。
基本內容https://en.wikipedia.org/wiki/Regular_expression?了解一樣東西,當然先從WIKI開始最好了。
// Regular Expression examples I had a S+ day today [A-Za-z0-9-_]{3,16} ffffdd-dd-dd v(d+)(.d+)* TotalMessages="(.*?)" <[^<>]>教程
http://deerchao.net/tutorials/regex/regex.htm?30分鐘入門教程,網上流傳甚廣
https://qntm.org/files/re/re.html?55分鐘教程【英文】,
http://regex.learncodethehardway.org/book/?一本簡單的書,每一節就是一塊內容
https://swtch.com/~rsc/regexp/regexp1.html?正則匹配原理解析
http://stackoverflow.com/tags/regex/info?stackoverflow 正則標簽,標簽下有值得點擊的鏈接,一些典型的問題
http://regexr.com/?正則學習測試于一身
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions?MDN出品,JavaScript方面內容
https://regex101.com/?in JavaScript, Python, PCRE 16-bit, generates explanation of pattern
https://www.debuggex.com/?正則驗證測試,清晰明了
https://mengzhuo.org/regex/?中文版正則驗證測試
http://refiddle.com/?測試工具
http://myregexp.com/?也是測試工具,都可以試一試
http://regex.alf.nu?闖關模式練習正則表達式,完成一個個正則匹配的測驗
http://regexone.com/?通過實際練習掌握正則表達式
https://regexcrossword.com/?正則挑戰,有不同難度,很豐富
http://callumacrae.github.io/regex-tuesday/?正則挑戰,完成正則匹配要求
https://msdn.microsoft.com/zh-cn/library/az24scfc.aspx?MSDN 微軟出品
http://www.jb51.net/tools/regex.htm?常用正則表達式,如匹配網址、日期啊這種,這個谷歌一搜很多的
https://www.cheatography.com/davechild/cheat-sheets/regular-expressions/?速查表地址,如下圖
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/112059.html
摘要:正則大法好,正則大法好,正則大法好,重要的事情說三遍。第二部分,這個部分是整個表達式的關鍵部分。學習正則如果還沒有系統學習正則表達式,這里提供一些網上經典的教程供大家學習。正則表達式使用單個字符串來描述匹配一系列匹配某個句法規則的字符串。 原文收錄在我的 GitHub博客 (https://github.com/jawil/blog) ,喜歡的可以關注最新動態,大家一起多交流學習,共同...
摘要:記錄一些項目中用到的正則工具,將持續更新如果對中的正則不太了解,可以參考一下中正則表達式必知必會字符串操作去除字符串兩邊的空格編碼對等字符轉義,避免攻擊找出重復最多的字符把字符串轉換為數組首先進行排序,這樣結果會把相同的字符放在一起,然后再 記錄一些項目中用到的正則工具,將持續更新... 如果對JS中的正則不太了解,可以參考一下JS 中正則表達式必知必會 1. 字符串操作 1.1 去除...
閱讀 3420·2021-10-20 13:49
閱讀 2793·2021-09-29 09:34
閱讀 3691·2021-09-01 11:29
閱讀 3080·2019-08-30 11:01
閱讀 838·2019-08-29 17:10
閱讀 866·2019-08-29 12:48
閱讀 2776·2019-08-29 12:40
閱讀 1346·2019-08-29 12:30