<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          別再說概念了!直接告訴我這些常用正則表達(dá)式是怎么寫出來的行不行?

          共 7125字,需瀏覽 15分鐘

           ·

          2022-04-14 16:19

          點(diǎn)擊上方 前端Q,關(guān)注公眾號

          回復(fù)加群,加入前端Q技術(shù)交流群


          作為一名程序員,不會寫正則表達(dá)式總感覺少了點(diǎn)什么,不要求你能把正則玩出花來,但最起碼要對常用的正則表達(dá)式手到擒來,剛畢業(yè)的我對于正則也是一頭霧水,不過學(xué)會它也就一篇教程的事情[1]

          本文我不會再浪費(fèi)帶寬把正則的規(guī)則再次重復(fù)一遍,而是從實際入手,直接告訴你為什么這么寫

          16進(jìn)制顏色

          按照規(guī)則來

          1. # 開頭
          2. 后面緊跟著6個字符或者3個字符作為結(jié)尾,這些字符可以是 a-f 的小寫字母、A-F的大寫字母、數(shù)字

          第一句,可以寫成 /^#/;第二句,[a-fA-F0-9] 表示任意的 a-f、A-F0-963的個數(shù)可以用 {6}、{3}進(jìn)行表示,那么3個字符就是 [a-fA-F0-9]{3},6個字符就是 [a-fA-F0-9]{6},這兩個都有可能,用一個或(|)符號來連接:([a-fA-F0-9]{6}|[a-fA-F0-9]{3}),最后結(jié)尾可以用個 $

          所有合到一起就是 /^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/

          鏈接

          目標(biāo)是匹配出協(xié)議、域名、端口號portpath、search

          1. 協(xié)議

          合法的協(xié)議有 http、https,還有一個是自適應(yīng)協(xié)議,即不明確加協(xié)議,跟當(dāng)前頁面的協(xié)議保持一致,所以以下都是合法的:http://toutiao.com、https://toutiao.com//toutiao.com。這三個協(xié)議組成的鏈接共同點(diǎn)是肯定有 // 字符串,在 //的前面可能是 https: 也可能是 http: 也可以沒有任何字符串 先按照 https:// 這種寫規(guī)則:^https:\/\/,其中的 s 字符可能有也可能沒有,所以使用 ? 修飾:^https?:\/\/,又因為 https?:可能沒有,所以這個字符串也用 ?修飾:^(https?:)?\/\/

          1. 域名

          域名的前面可能是 //,從 //往后面匹配,只要沒有代表 :port、代表 search?、代表 path/,那么就都屬于域名:[^?:/]+

          1. 端口號 port

          端口號肯定以 : 開頭,后面跟著的只要是數(shù)字就都屬于 port:\d+,由于不一定有端口號,所以用 ? 修飾:(:\d+)?

          1. path

          肯定以 / 開頭,只要不遇到代表 search?,那么就都屬于 path\/[^?]*,由于可能沒有 path,所以用 ? 修飾:(\/[^?]*)? 5. search 肯定以 ? 開頭,后面所有的字符都屬于 search(不考慮 hash 路由):\?(.*),由于可能沒有 search,所以用 ? 修飾:(\?.*)?

          最后把上面所有規(guī)則合起來就是提取鏈接的完整正則了,考慮到需要精確提取所需要的部分,所以會對所需要提取的部分加上小括號,結(jié)果為:/^((https?):)?\/\/([^?:/]+)(:(\d+))?(\/[^?]*)?(\?(.*))?/

          郵箱

          以前在知乎上看到過一段郵箱正則,號稱是最符合標(biāo)準(zhǔn)的正則表達(dá)式,那條正則的體積好像有幾十KB吧,總之很長,現(xiàn)在找不到了,這里只關(guān)注常用的郵箱格式,規(guī)則:名稱允許漢字、字母、數(shù)字,下劃線,中劃線,域名可以有數(shù)字、字母、下劃線、中劃線組成

          漢字的范圍是 [\u4e00-\u9fa5],字母的范圍是 [a-zA-Z],數(shù)字的范圍是 [0-9],合起來組成郵箱的名稱 ^[A-Za-z0-9-_\u4e00-\u9fa5]+

          域名是 [a-zA-Z0-9_-]+,域名后綴可以是多級域名 (\.[a-zA-Z0-9_-]+)+

          上面組合起來就是 ^[A-Za-z0-9-_\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$

          手機(jī)號

          手機(jī)號的號段可能是會增加的,所以在實際場景中不建議限制得太死了

          本正則按照以下規(guī)則編寫:

          1. 11位數(shù)字,以數(shù)字 1 開頭,即 ^1
          2. 接下來的數(shù)字如果是 3,那么 3后面可以跟一個任意數(shù)字,即 3\d;如果是 4,那么 4后面可以跟一個5-9之間的數(shù)字,即 4[5-9];如果是 5,那么 5后面可以跟一個0-35-9之間的數(shù)字,即 5[0-35-9];如果是 6,那么 6后面可以跟 25、67 其中一個數(shù)字,即 6[2567];如果是 7,那么 7后面可以跟一個0-8之間的數(shù)字,即 7[0-8];如果是 8,那么 8后面可以跟一個任意數(shù)字,即 8\d;如果是 9,那么 9后面可以跟一個0-35-9之間的數(shù)字,即 9[0-35-9]
          3. 最后 8位可以是任意數(shù)字

          上述三步合起來就是 /^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/

          數(shù)字/貨幣金額

          1. 支持負(fù)數(shù)

          負(fù)號用 -負(fù)號,且必須在第一位,即 ^-,再加個 ? 用于表示這個負(fù)號可以有也可以沒有,即 ^-? 2. 支持千分位分隔(沒有也沒關(guān)系) 如果有千分位,則千分位的后面必然跟著三位數(shù)字(否則這個千分號就不應(yīng)該加了),千分位前面最少一位、最多三位數(shù)字,那么可以寫成 \d{1,3},\d{3},再精簡下,千分位前面的數(shù)字其實可以不用限制,因為只要超過三位肯定就有千分位,就會被 \d{3}捕獲,所以 \d{1,3} 換成 \d+就行了,因為符合千分位的可以有多個也可能沒有,所以寫成 \d+(,\d{3})* 3. 如果有小數(shù),則小數(shù)點(diǎn)后最多兩位 小數(shù)點(diǎn)就是 \.,后面跟著最多兩位數(shù)字 \d{1,2},可能有小數(shù)也可能沒有,所以整體需要再加個 ? 符號,即 (\.\d{1,2})?

          最終規(guī)則 /^-?\d+(,\d{3})*(\.\d{1,2})?$/

          身份證號

          這里只看 2代身份證,18位數(shù)字 最后一位是校驗位,可能為數(shù)字或字符X

          1. 第一位數(shù)字在 [1-9] 閉區(qū)間內(nèi),后面緊跟著5位任意數(shù)字,寫成 ^[1-9]\d{5}

          2. 再緊跟著的四位數(shù)字代表年份(YYYY),因為目前有身份證的人最早是19世紀(jì)最晚21世紀(jì),所以這四個數(shù)字中的前兩位只看是 18、19、20,即 (18|19|20),后兩位則可以是任意數(shù)字,即 \d{2}

          3. 再緊跟著兩位數(shù)字是月(MM),月份只可能是 [1-12]閉區(qū)間,所以可以寫成 (01|02|03|04|05|06|07|08|09|10|11|12),前九位的開頭都是 0,第二位是 [1-9] 內(nèi)的數(shù)字,所以簡化成 (0[1-9]|10|11|12)

          4. 再緊跟著兩位數(shù)字是日(DD),范圍是 [01-31],可以將這31個數(shù)字羅列出來,當(dāng)然也可以精簡下,看成是 [00-09]、[10-29]、[30-31]的組合,即 (0[1-9]|[1-2]\d|30|31)

          5. 再緊跟著三位數(shù)字是順序碼,即 \d{3}

          6. 最后一位是校驗碼,可以是數(shù)字也可以是 X,即 [\dX]

          最終規(guī)則 /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|10|11|12)(0[1-9]|[1-2]\d|30|31)\d{3}[\dX]$/

          密碼校驗

          最少6位,包括至少1個大寫字母,1個小寫字母,1個數(shù)字,1個特殊字符

          對于 至少1個大寫字母 這條規(guī)則,這個大寫字母的位置是不固定的,只要有就行,如果只有這一條規(guī)則的話,正則可以寫成 ^\S*[A-Z]+\S*$,\S 匹配任意非空白字符,這個規(guī)則即代表大寫字母的前面、后面可以跟著任意個(包括0個)非空白字符

          但除此之外還需要滿足最少1個小寫字母,1個數(shù)字,1個特殊字符,最少6位,你可以將這幾條規(guī)則都單獨(dú)寫出正則,然后目標(biāo)字符串跟這5條正則一一匹配,只要全部能匹配上就是對的,寫成 js 代碼就是:

          function match(s: string{
            return /^\S*[A-Z]+\S*$/.test(s)
              && /^\S*[a-z]+\S*$/.test(s)
              && /^\S*[0-9]+\S*$/.test(s)
              && /^\S*[!@#$%^&*?]+\S*$/.test(s)
              && /^\S*\S{6,}\S*$/.test(s)
          }
          復(fù)制代碼

          如果就想在一條正則里實現(xiàn)這些校驗?zāi)?,也是可以的,需要借?零寬度正預(yù)測先行斷言(?=exp)),代表 匹配exp前面的位置

          有了這個東西,就可以把上面5條規(guī)則寫到一起去了:/^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*?])\S*$/

          這條正則前面后面的 \S* 還是之前的意思不變,中間是提取了5條規(guī)則的個性部分,然后通過 ?= 放在一起了,把規(guī)則里所有的 ?=去掉行不行?不行,因為如果去掉的話,首先就有順序上的沖突了,例如上面的規(guī)則,如果把所有的 ?=去掉,就代表著 數(shù)字必須在大寫字母前面,大寫字母必須在小寫字母前面,特殊字母必須在小寫字母前面(除此之外整個正則也是有問題的)

          你可以認(rèn)為 ?= 在匹配的時候會忽略掉其他的 ?=,只關(guān)心自己的前面能不能匹配成功,有多個 ?=,則這多個 ?= 都是只關(guān)心自己,忽略其他,但整條正則最后的結(jié)果是所有 ?= 匹配結(jié)果的并集,計算邏輯和上面的 js 是差不多的

          提取 HTML 標(biāo)簽數(shù)據(jù)

          要提取的標(biāo)簽字符串類似于 <div class="header-box" name="header">

          只是正則話無法完成,需要借助 js

          首先,把標(biāo)簽的屬性提取出來

          這段標(biāo)簽包含標(biāo)簽開始符號、tag、屬性字符串、標(biāo)簽結(jié)束符號

          開始符號是 <,標(biāo)簽名緊跟著開始符號,且只要沒遇到空白符就都是標(biāo)簽名,所以連起來就是 <\w+\s*

          在開始符號+標(biāo)簽名,和 結(jié)束符號的中間,都是屬性,結(jié)束符號是 >,所以只要沒遇到結(jié)束符號 >,就認(rèn)為是屬性字符串,用到了反向選擇 [^>]*\s*>,合起來就是 /<\w+\s*[^>]*\s*>/,為了能捕獲屬性字符串,加個小括號,即 /<\w+\s*([^>]*)\s*>/

          const str = `<div class="header-box" name="header">`
          const mt = str.match(/<\w+\s*([^>]*)\s*>/)
          // properties 即 屬性字符串,即 class="header-box" name="header"
          const properties = mt[1]
          復(fù)制代碼

          取到了 class="header-box" name="header" 之后,再對其進(jìn)行處理,觀察規(guī)律,每個屬性的鍵值對之間肯定存在空白符,不過卻不能通過空白符來直接分割,因為屬性值是可以存在空白符的,例如 class="a b"

          由于可能是自閉合標(biāo)簽,自閉合標(biāo)簽的最后有沒有 / 都是合法的,例如 <hr>hr />都是合法的,所以需要兼容下:/<\w+\s*([^>]*)\s*\/?>/

          但屬性名是可以確定的,它可能是 = 左邊不包括空白符的內(nèi)容,再次用到反向選擇,從左往右匹配,反向選擇既不是=也不是不是空白符的內(nèi)容,即 [^\s=]+

          雖然不確定屬性值是否包含空白符,但有個是確定的,即屬性值必然被引號包圍,所以直接取 = 右側(cè)所有引號的內(nèi)容即可,=".*?"

          不過還有個問題,引號不僅可以是單引號還可以是雙引號,即 =".*?"='.*?' 都行,如果第一個引號是雙引號開頭那么對應(yīng)的第二個引號也必然是雙引號,反義單引號亦然,這里需要用到捕獲的規(guī)則了 =(["']).*?\1,\1的意思是這塊匹配的內(nèi)容跟第一捕獲組一樣,第一捕獲組也就是 ["'],如果第一捕獲組匹配的是雙引號,那么 \1 就代表雙引號,否則就代表單引號

          至此整個正則為 [^\s=]+=(["']).*?\1

          不過還有個問題,屬性是可以沒有屬性值的,例如 <input type="checkbox" checked />,這里 checked 就是可以不寫屬性值的,所以再兼容下:/[^\s=]+(=(["']).*?\2)?/,又因為希望捕捉屬性和屬性值,所以給屬性和屬性值加個小括號:/([^\s=]+)(=(["'])(.*?)\3)?/

          上面的代表就可以繼續(xù)寫了

          const str = `<div class="header-box" name="header">`
          const mt = str.match(/<\w+\s*([^>]*)\s*>/)
          // properties 即 屬性字符串,即 class="header-box" name="header"
          const properties = mt[1]
          const mt1 = properties.match(/([^\s=]+)(=(["'])(.*?)\3)?/g)
          const obj = {}
          if (mt1) {
            mt1.forEach(p => {
              const kv = p.trim().split('=')
              obj[kv[0].trim()] = kv[1].trim().slice(1-1)
            })
          }
          // obj => { class: 'header-box', name: 'header' }
          復(fù)制代碼

          小結(jié)

          學(xué)會正則的最接途徑就是勤加練習(xí),平時遇到可以用正則解決的問題,就嘗試著正則解決,或許你一開始寫不出來,但可以去網(wǎng)上看看別人是怎么寫的,再自己獨(dú)立寫一遍,寫得多了自然就會了,沒什么訣竅,無非就是對正則規(guī)則的熟練掌握罷了

          最后

          字節(jié)跳動-直播變現(xiàn)與千川部門招聘啦!

          不低于 10hc(騙人是小狗),北京、上海、杭州都可以,而且是 急招,就差一個程序員了的那種

          經(jīng)驗不限,接受實習(xí)

          之前投過字節(jié)其他部門沒過的也沒關(guān)系(面試沒過不一定代表能力不行,也可能是眼緣不夠),可以繼續(xù)面我這個部門(萬一就看對眼了呢,畢竟我們部門真的缺人),有興趣的可將簡歷發(fā)我郵箱 kother\@foxmail.com[2] ,所有發(fā)我簡歷的人,保證全程跟進(jìn)并反饋面試進(jìn)度,有問必答(在不違反公司規(guī)章制度的前提下),杜絕簡歷一投石沉大海的糟糕體驗

          救救孩子,快來把我的需求分點(diǎn)走吧!

          團(tuán)隊介紹 直播變現(xiàn)與千川,負(fù)責(zé)優(yōu)化字節(jié)跳動中國區(qū)流量的直播廣告以及短視頻電商廣告,負(fù)責(zé)巨量千川的平臺建設(shè)、算法優(yōu)化、廣告產(chǎn)品和運(yùn)營策略的落地。首要目標(biāo)是:借由字節(jié)強(qiáng)大的算法工程能力,發(fā)揮直播體裁和電商閉環(huán)的天然優(yōu)勢,進(jìn)一步提升中國區(qū)商業(yè)化收入。生活服務(wù)業(yè)務(wù)依托于抖音,抖音極速版等平臺,致力于促進(jìn)用戶與本地服務(wù)的連接;過去一年,生活服務(wù)業(yè)務(wù)開創(chuàng)了全新的視頻種草和交易體驗,讓更多用戶通過抖音發(fā)現(xiàn)線下的好去處,也幫助眾多本地商家拓展了新的經(jīng)營陣地。我們期待你的加入,希望下一個參與服務(wù)百萬商家,影響億級消費(fèi)者,引領(lǐng)營銷革命的就是你!

          團(tuán)隊優(yōu)勢

          1. 技術(shù):以業(yè)務(wù)為最終導(dǎo)向,即使作為研發(fā)角色,也能夠接觸一線客戶,通過技術(shù)方案解決客戶問題,技術(shù)方案涉及廣告投放系統(tǒng)中召回、粗排、精排、出價、排序等多個環(huán)節(jié),能夠深入全面地理解廣告變現(xiàn)系統(tǒng)的各個環(huán)節(jié)的內(nèi)部原理。
          2. 成長:字節(jié)電商GMV仍然在高速提升,在滿足購買需求時,短視頻和直播體裁具備顛覆性的優(yōu)勢,業(yè)務(wù)成長空間非常大。
          3. 機(jī)遇:字節(jié)電商的購買體驗更加多元,包含:商品、視頻、直播流、達(dá)人、粉絲關(guān)系、直播互動等等,相比傳統(tǒng)貨架式電商,scope更大,個人的發(fā)展機(jī)會更多。


          關(guān)于本文

          來自:清夜

          https://juejin.cn/post/7073360739410378760


          往期推薦


          秒??!答好這5個問題,就入門Docker了
          (字節(jié)/華為/美團(tuán))前端面經(jīng)記錄冷冷清清的金三銀四
          實現(xiàn)圖片本地化 ServiceWorker + IndexedDB

          最后


          • 歡迎加我微信,拉你進(jìn)技術(shù)群,長期交流學(xué)習(xí)...

          • 歡迎關(guān)注「前端Q」,認(rèn)真學(xué)前端,做個專業(yè)的技術(shù)人...

          點(diǎn)個在看支持我吧
          瀏覽 36
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一级a一级a爰片免费啪啪女女 | 逼特逼在线观看视频 | 99热免费在线观看 | 黄色色情网站在线观看 | 黄片免费观看 |