摘要:什么是正則表達式正則表達式是用于匹配字符串中字符組合的模式。在中,正則表達式也是對象。正則表達式存在于大部分的編程語言,就算是在寫時也會不經意的用到正則。第二個參數卻是可以傳入一個字符串,也可以傳入一個回調函數。
什么是正則表達式
正則表達式是用于匹配字符串中字符組合的模式。在 JavaScript中,正則表達式也是對象。
這些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、replace、search 和 split 方法。
正則表達式存在于大部分的編程語言,就算是在寫shell時也會不經意的用到正則。
比如大家最喜歡的rm -rf ./*,這里邊的*就是正則的通配符,匹配任意字符。
在JavaScript也有正則表達式的實現,差不多就長這個樣子:/d/(匹配一個數字)。
個人認為正則所用到的地方還是很多的,比如模版字符的替換、解析URL,表單驗證 等等一系列。
如果在Node.js中用處就更為多,比如請求頭的解析、文件內容的批量替換以及寫爬蟲時候一定會遇到的解析HTML標簽。
贅述那些特殊字符的作用并沒有什么意義,浪費時間。
推薦MDN的文檔:基礎的正則表達式特殊字符
關于正則表達式,個人認為以下幾個比較重要:
貪婪模式與非貪婪模式P.S. 關于貪婪模式和非貪婪模式,發現有些地方會拿這樣的例子:
/.+/ // 貪婪模式 /.+?/ // 非貪婪模式
僅僅拿這樣簡單的例子來說的話,有點兒扯淡
// 假設有這樣的一個字符串 let html = "text1text2
" // 現在我們要取出第一個`span`中的文本,于是我們寫了這樣的正則 html.match(/(.+)/) // 卻發現匹配到的竟然是 text1text2 // 這是因為 我們括號中寫的是 `(.+)` .為匹配任意字符, +則表示匹配一次以上。 // 當規則匹配到了`text1`的時候,還會繼續查找下一個,發現`<`也命中了`.`這個規則 // 于是就持續的往后找,知道找到最后一個span,結束本次匹配。 // 但是當我們把正則修改成這樣以后: html.match(/(.+?)/) // 這次就能匹配到我們想要的結果了 // `?`的作為是,匹配`0~1`次規則 // 但是如果跟在`*`、`+`之類的表示數量的特殊字符后,含義就會變為匹配盡量少的字符。 // 當正則匹配到了text1后,判斷后邊的命中了規則,就直接返回結果,不會往后繼續匹配。
簡單來說就是:
貪婪模式,能拿多少拿多少
非貪婪模式,能拿多少拿多少
捕獲組/123(d+)0/ 括號中的被稱之為捕獲組。
捕獲組有很多的作用,比如處理一些日期格式的轉換。
let date = "2017-11-21" date.replace(/^(d{4})-(d{2})-(d{2})$/, "$2/$3/$1")
又或者可以直接寫在正則表達式中作為前邊重復項的匹配。
let template = "hello helloworl" template.match(/(w+) 1/) // => hello hello // 我們可以用它來匹配出month和day數字相同的數據 let dateList = ` 2017-10-10 2017-11-12 2017-12-12 ` dateList.match(/^d{4}-(d{2})-(1)/gm) // => ["2017-10-10", "2017-12-12"]非捕獲組
我們讀取了一個文本文件,里邊是一個名單列表
我們想要取出所有Stark的名字(但是并不想要姓氏,因為都叫Stark),我們就可以寫這樣的正則:
let nameList = ` Brandon Stark Sansa Stark John Snow ` nameList.match(/^w+(?=s?Stark)/gm) // => ["Brandon", "Sansa"]
上邊的(?=)就是非捕獲組,意思就是規則會被命中,但是在結果中不會包含它。
比如我們想實現一個比較常用的功能,給數組添加千分位:
function numberWithCommas (x = 0) { return x.toString().replace(/B(?=(d{3})+(?!d))/g, ",") } numberWithCommas(123) // => 123 numberWithCommas(1234) // => 1,234
B代表匹配一個非單詞邊界,也就是說,實際他并不會替換掉任何的元素。
其次,后邊的非捕獲組這么定義:存在三的倍數個數字(3、6、9),并且這些數字后邊沒有再跟著其他的數字。
因為在非捕獲組中使用的是(d{3})+,貪婪模式,所以就會盡可能多的去匹配。
如果傳入字符串1234567,則第一次匹配的位置在1和2之間,第二次匹配的位置在4和5之間。
獲得的最終字符串就是1,234,567
創建RegExp對象有兩種方式:
直接字面量的聲明:/d/g
通過構造函數進行創建:new RegExp("d", "g")
RegExp對象提供了兩個方法:
方法執行傳入一個字符串,然后對該字符串進行匹配,如果匹配失敗則直接返回null
如果匹配成功則會返回一個數組:
let reg = /([a-z])d+/ let str = "a233" let result = reg.exec(str) // => ["a233", "a", ...]
P.S. 如果正則表達式有g標識,在每次執行完exec后,該正則對象的lastIndex值就會被改變,該值表示下次匹配的開始下標
let reg = /([a-z])d+/g let str = "a233" reg.exec(str) // => ["a233", "a", ...] // reg.lastIndex = 4 reg.exec(str) // => null
方法用來檢查正則是否能成功匹配該字符串
let reg = /^Hello/ reg.test("Hello World") // => true reg.test("Say Hello") // => false
test方法一般來說多用在檢索或者過濾的地方。
比如我們做一些篩選filter的操作,用test就是一個很好的選擇。
// 篩選出所有名字為 Niko的數據 let data = [{ name: "Niko Bellic" }, { name: "Roman Bellic"}] data.filter(({name}) => /^Niko/.test(name)) // => [{ name: "Niko Bellic" }]String對象
除了RegExp對象實現的一些方法外,String同樣提供了一套方法供大家來使用。
傳入一個正則表達式,并使用該表達式進行匹配;
如果匹配失敗,則會返回-1
如果匹配成功,則會返回匹配開始的下標。
可以理解為是一個正則版的indexOf
"Hi Niko".search(/Niko/) // => 3 "Hi Niko".search(/Roman/) // => -1 // 如果傳入的參數為一個字符串,則會將其轉換為`RegExp`對象 "Hello".search("llo") // => 2
split方法應該是比較常用的,用得最多的估計就是[].split(",")了。。
然而這個參數也是可以塞進去一個正則表達式的。
"1,2|3".split(/,||/) // => [1, 2, 3] // 比如我們要將一個日期時間字符串進行分割 let date = "2017-11-21 23:40:56" date.split(/-|s|:/) // 又或者我們有這么一個字符串,要將它正確的分割 let arr = "1,2,3,4,[5,6,7]" arr.split(",") // => ["1", "2", "3", "4", "[5", "6", "7]"] 這個結果肯定是不對的。 // 所以我們可以這么寫 arr.split(/,(?![,d]+])/) // => ["1", "2", "3", "4", "[5,6,7]"]
該條規則會匹配,,但是,后邊還有一個限定條件,那就是絕對不能出現數字+,的組合并且以一個]結尾。
這樣就會使[4,5,6]里邊的,不被匹配到。
match方法用來檢索字符串,并返回匹配的結果。
如果正則沒有添加g標識的話,返回值與exec類似。
但是如果添加了g標識,則會返回一個數組,數組的item為滿足匹配條件的子串。
這將會無視掉所有的捕獲組。
拿上邊的那個解析HTML來說
let html = "text1text2
" html.match(/(.+?)/g) // => ["text1", "text2"]
replace應該是與正則有關的應用最多的一個函數。
最簡單的模版引擎可以基于replace來做。
日期格式轉換也可以通過replace來做。
甚至match的功能也可以通過replace來實現(雖說代碼會看起來很丑)
replace接收兩個參數
replace(str|regexp, newStr|callback)
第一個參數可以是一個字符串 也可以是一個正則表達式,轉換規則同上幾個方法。
第二個參數卻是可以傳入一個字符串,也可以傳入一個回調函數。
當傳入字符串時,會將正則所匹配到的字串替換為該字符串。
當傳入回調函數時,則會在匹配到子串時調用該回調,回調函數的返回值會替換被匹配到的子串。
"Hi: Jhon".replace(/Hi:s(w+)/g, "Hi: $1 Snow") // => Hi: Jhon Snow "price: 1".replace(/price:s(d)/g, (/* 匹配的完整串 */str, /* 捕獲組 */ $1) => `price: ${$1 *= 10}`) // => price: 10一些全新的特性
前段時間看了下ECMAScript 2018的一些草案,發現有些Stage 3的草案,其中有提到RegExp相關的,并在chrome上試驗了一下,發現已經可以使用了。Lookbehind assertions(應該可以叫做回溯引用吧)
同樣也是一個非捕獲組的語法定義
語法定義:
let reg = /(?<=Pre)w/ reg.test("Prefixer") // => true reg.test("Prfixer") // => false
設置匹配串前邊必須滿足的一些條件,與(?=)正好相反,一前一后。
這個結合著(?=)使用簡直是神器,還是說解析HTML的那個問題。
現在有了(?<=)以后,我們甚至可以直接通過一個match函數拿到HTML元素中的文本值了。
let html = "Named capture groups(命名捕獲組)text1text2
" html.match(/(?<=)(.+?)(?=)/g) // => ["text1", "text2"]
我們知道,()標識這一個捕獲組,然后用的時候就是通過1或者$1來使用。
這次草案中提到的命名捕獲組,就是可以讓你對()進行命名,在使用時候可以用接近變量的用法來調用。
語法定義:
let reg = /(?d{4})-(? d{2})-(? d{2})/ "2017-11-21".match(reg)
在match的返回值中,我們會找到一個groups的key。
里邊存儲著所有的命名捕獲組。
let reg = /(?d{4})-(? d{2})-(? d{2})/ "2017-11-21".replace(reg, "$ /$ /$ ") // => 21/11/2017
let reg = /d{4}-(?參考資料d{2})-k / reg.test("2017-11-11") // => true reg.test("2017-11-21") // => false
MDN-正則表達式
RegExp named capture groups
RegExp lookbehind assertions
在線正則匹配規則
個人GitHub:https://github.com/jiasm
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93719.html
摘要:而當我們時這個是一個類我們稱呼它為函數。后兩者是常量用于忽略換行符和大小寫。這就會導致很多難以覺察的潛在。結論無論是使用還是第一個要求是代碼能夠正常運行其次根據代碼維護性團隊編碼風格來確定選擇哪一種方案。 ...
摘要:添加依賴到如何使用依賴當你再興建一個文件的時候,就不需要一個個插件安裝了,將文件復制到當前文件下,并輸入,即通過里的依賴關系,自動把依賴安裝好了。第四步新建配置文件默認的配置文件在項目目錄下為。 WilsonLius blog 首發地址 前言 早就想嘗試webpack的,卻一直沒有時間,恰逢周末,又時值最近在公司實習的時候嘗到用fekit做模塊化的構建工具的爽。所以就開始以公司的項目結...
摘要:函數節流用途如調整瀏覽器大小,或者用戶輸入信息,導致反復提交接口調用方法判斷手機端訪問獲取地址欄參數返回頂部當滾動條的位置處于距頂部像素以下時,跳轉鏈接出現,否則消失當點擊跳轉鏈接后,回到頁面頂部位置正則檢測手機號郵箱 1.JavaScript 函數節流用途:如調整瀏覽器大小,或者用戶輸入信息,導致反復提交接口 function throttle(method,context) { ...
摘要:目前正在開發一個系統,對于前端模塊化與打包這塊出現了一些選擇。采用模塊化及打包由于項目比較小,稍微了解后,覺得沒必要采用。組件化,目前比較流行的如等。項目較小需要交互更新頁面的并不多,沒有采用。 目前正在開發一個python markdown wiki系統,對于前端模塊化與打包這塊出現了一些選擇。1、采用webpack模塊化及打包由于項目比較小,稍微了解后,覺得沒必要采用webpack...
閱讀 2101·2021-11-18 10:02
閱讀 2850·2021-09-04 16:41
閱讀 1142·2019-08-30 15:55
閱讀 1405·2019-08-29 17:27
閱讀 1070·2019-08-29 17:12
閱讀 2535·2019-08-29 15:38
閱讀 2855·2019-08-29 13:02
閱讀 2831·2019-08-29 12:29