成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

正則從零到簡單分析html標(biāo)簽

antz / 1599人閱讀

摘要:對(duì)于正則之前一直是一個(gè)百度程序員也許超過一半甚至更多的程序員也是那么這次來學(xué)習(xí)一下正則表達(dá)式事出有因這部分介紹一下需求的由來與主要內(nèi)容無關(guān)工作上有了這樣的需求端從來的數(shù)據(jù)格式是也就是文章內(nèi)容并夾雜著諸多標(biāo)簽和嵌套然而正在開發(fā)的是項(xiàng)目的標(biāo)簽

對(duì)于正則之前一直是一個(gè)"百度程序員", 也許超過一半甚至更多的程序員也是, 那么這次來學(xué)習(xí)一下正則表達(dá)式.

事出有因

這部分介紹一下需求的由來, 與主要內(nèi)容無關(guān).

工作上有了這樣的需求:

web端從ueditor來的數(shù)據(jù)格式是html, 也就是

文章內(nèi)容

, 并夾雜著諸多標(biāo)簽和嵌套.

然而正在開發(fā)的是react-native項(xiàng)目, rn的標(biāo)簽和html完全不兼容, 是View, Text, Image等.

那么把從web存入的數(shù)據(jù)讀取到rn上就出了大麻煩, 甚至有些地方要進(jìn)行跳轉(zhuǎn), 有些圖片要顯示, 那么怎么辦呢.

通過百度"js如何驗(yàn)證郵箱"已經(jīng)無法滿足需求了, 只能學(xué)一下了.

目標(biāo)

萬事有目標(biāo), 我們要把一下內(nèi)容轉(zhuǎn)換成rn的內(nèi)容:

嘿嘿嘿拖過來的圖片哦
abcd

轉(zhuǎn)換結(jié)果是:

嘿嘿嘿

拖過來的圖片哦

a

b
...

本文會(huì)從零基礎(chǔ)出發(fā)達(dá)成這個(gè)目標(biāo).

講解順序: 正則介紹 => 正則語法系統(tǒng) => 簡單的例子講解 => 嘗試實(shí)現(xiàn)目標(biāo)以及碰到的問題 => 實(shí)現(xiàn)目標(biāo)

什么是正則

初中時(shí)候?qū)W的通配符, 用?代表一個(gè)任意字符, 用*代表任意個(gè)任意字符來進(jìn)行搜索, 正則也是如此. 比如:

123[abc]匹配以下哪組字符?

123c

123d

123e

123f

選了1的朋友你已經(jīng)知道正則是什么了. 123[abc]就是正則, 代表匹配內(nèi)容為: 前三個(gè)字符分別為123, 第四個(gè)字符是abc中的一個(gè), 這個(gè)正則遇到123a, 123b, 123c都可以匹配成功, 其他任何都匹配失敗.

正則語法

百度了正則表達(dá)式看到的東西都用了很多術(shù)語, 讓人有點(diǎn)犯渾. 我經(jīng)過學(xué)習(xí)把正則抽象為兩個(gè)部分: 內(nèi)容修飾.

看到一長串正則覺得稀里嘩啦, 但是里面的每個(gè)符號(hào)一定都屬于內(nèi)容或是修飾.

內(nèi)容

內(nèi)容的形式有3種:

直接匹配: 舉例就是剛才的123[abc]中的123, 這種匹配需要完全吻合才能匹配, 123就唯一匹配123.

范圍匹配: 用中括號(hào)表示, 也就是剛才例子中的[abc]. 這種情況也就是三選一. 任意匹配abc, 而不是匹配abc. 還有兩種形式: 加-來表示范圍, 比如[a-z]; 表示排除范圍內(nèi)的^, 比如[^abc]

匹配并選擇緩存到子匹配: 用圓括號(hào)表示, 圓括號(hào)中的內(nèi)容語法是"直接匹配"但會(huì)被記入緩存作為子匹配, 我記得我最初接觸正則就是url rewrite, 寫了url正則之后用$1, $2來重寫url.

在范圍匹配中, 我們經(jīng)常會(huì)用: 數(shù)字/字母, 也就是[0-9], [a-zA-Z], 但是經(jīng)常用到重復(fù)地寫麻煩又看不能裝逼了, 所以產(chǎn)生了一些快捷方式: d代表[0-9], w代表[0-9a-zA-Z_]這正好是常用的用戶名和密碼的規(guī)則.

這里深入一下圓括號(hào)匹配的兩個(gè)點(diǎn). 作為拓展, 可以先不看一下的內(nèi)容直接到下一部分.

因?yàn)閳A括號(hào)中可以用|符號(hào)來表示或的關(guān)系, 但有時(shí)候又不想被加入緩存. 于是可以用?:來表示不需要緩存. 例子:hello (?:world|regular expression), 用來匹配hello world或者hello regular expression, 但又不需要把world儲(chǔ)存為緩存.

如果之前已經(jīng)用圓括號(hào), 那么期望之后出現(xiàn)同樣的內(nèi)容, 可以用1這樣加數(shù)字來表示. 舉個(gè)例子: 單引號(hào)和雙引號(hào), 我們要匹配"123"或者"123", 但是要保持引號(hào)一致. ("|")1231就可以解決問題.

修飾

我把修飾部分分為數(shù)量修飾和邊界修飾.

數(shù)量修飾: 符號(hào)為{}, 想到了谷歌: go{2,4}gle這個(gè)正則可以匹配google, gooogle, goooogle, 代表這個(gè)o可以匹配2或者4次. 當(dāng)然只是為了舉例可以枚舉, 因?yàn)?b>go{2,}gle代表可以無限個(gè)o, 這樣舉例不方便.

與之前的范圍匹配一樣, 數(shù)量修飾也有快捷符號(hào): ?代表{0,1}, *代表{0,}, +代表{1,}. 都很形象, 不用死記, 就像剛才的d for digital, w for word. 看過一個(gè)例子: colou?r 這里的?表示可有可無, 美式和英式的拼寫都可以匹配.

另外在"無上限"的數(shù)量的右邊加?代表不貪婪匹配, 會(huì)匹配數(shù)量最少的內(nèi)容. 舉例: a+匹配aaaaa的結(jié)果為aaaaa, a+?匹配aaaaa的結(jié)果為a.

邊界修飾: ^表示字符串的頭, $表示字符串的尾, 表示字母與空格間的位置. 用來給匹配定位, 具體用法在實(shí)際中操作就會(huì)有具體感受了.

另外, 正則有一種匹配模式是m, 多行匹配模式, 這個(gè)情況里^$也能匹配每一行的開頭和結(jié)尾.

javascript相關(guān)函數(shù)

首先明確正則是"正則表達(dá)式"與"字符串"發(fā)生的匹配關(guān)系.

js有個(gè)對(duì)象是RegExp, 使用方法是new RegExp(pattern, mode), 或者是用/包裹的字面量: /pattern/mode.

這里發(fā)現(xiàn)提到了mode匹配模式, 一共三種:

g: 全局匹配, 匹配到一次不會(huì)停止, /a/匹配aaa, 如果沒有g(shù)結(jié)果是一個(gè)a, 有g(shù)結(jié)果是3個(gè)a.

i: 忽略大小寫.

m: 多行模式. 和之前提到的有聯(lián)動(dòng).

三個(gè)模式不互斥, 疊加的, 也就是可以new RegExp(patter, "gin").

正則的方法有:

.test(): 返回是否匹配成功, true或者false.

.exec(): 失敗返回null, 成功返回?cái)?shù)組, 位置0是匹配內(nèi)容, 之后是圓括號(hào)匹配的內(nèi)容. 要注意的是exec是忽略"g"模式的.

字符串的方法:

.replace(pattern, replacement): replacement可以字符串或方法, 方法的話參數(shù)是匹配到的內(nèi)容.

.match(pattern): 返回?cái)?shù)組, 所有匹配到的內(nèi)容.

分析一些簡單常用的例子 是否小數(shù)
function isDecimal(strValue )  {  
   var  objRegExp= /^d+.d+$/;
   return  objRegExp.test(strValue);  
}  

d代表數(shù)字, +代表至少有1個(gè)數(shù)字, .轉(zhuǎn)移小數(shù)點(diǎn).

連起來看就是: 至少一個(gè)數(shù)字(d+) 小數(shù)點(diǎn)(.) 至少一個(gè)數(shù)字(d+) .

^$代表頭尾, 真?zhèn)€字符串是小數(shù)的全部, 而不是包含小數(shù).

是否中文名
function ischina(str) {
    var reg=/^[u4E00-u9FA5]{2,4}$/;   /*定義驗(yàn)證表達(dá)式*/
    return reg.test(str);     /*進(jìn)行驗(yàn)證*/
}

這個(gè)范圍是中文的編碼范圍: [u4E00-u9FA5], {2,4}匹配2~4個(gè). 也就是匹配2~4個(gè)中文.

是否八位數(shù)字
function isStudentNo(str) {
    var reg=/^d{8}$/;   /*定義驗(yàn)證表達(dá)式*/
    return reg.test(str);     /*進(jìn)行驗(yàn)證*/
}
是否電話號(hào)碼
function isTelCode(str) {
    var reg= /^((0d{2,3}-d{7,8})|(1[3584]d{9}))$/;
    return reg.test(str);
}

分兩個(gè)部分: 座機(jī)號(hào)和手機(jī)號(hào), 用|隔開了.

座機(jī)號(hào): 0開頭的三位數(shù)或四位數(shù) 短杠 7~8位數(shù)字.

手機(jī)號(hào): 第一位1, 第二位3584的一個(gè), 剩下由9個(gè)數(shù)字湊滿11位電話.

郵箱地址
function IsEmail(str) {
    var reg=/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+$/;
    return reg.test(str);
}
邁向目標(biāo)

這個(gè)章節(jié)開始整理實(shí)現(xiàn)需求的思路.

先回憶一下正則的規(guī)則, 其實(shí)很簡單, 和加減乘除一樣, 有各種符號(hào): [], (), |, -, {}, +, *, ?. 當(dāng)然也可以很復(fù)雜, 因?yàn)橐埠图訙p乘除一樣, 可以嵌套, 而正則的符號(hào)本來就多, 嵌套起來更是暈, 有一些符號(hào)在不同地方有不同作用, 比如^.(思考題: 分析一下這兩個(gè)符號(hào)有哪些作用, 在什么場景).

那么我們的目標(biāo)是: 把一段html分析稱rn的標(biāo)簽.

因?yàn)閞n沒有parse的功能, 所以不可以使用replace. (replace是代碼高亮的常用手段).

所以我們必須把html分解成js對(duì)象, 再從js對(duì)象里去分析輸出rn標(biāo)簽.

因?yàn)閔tml標(biāo)簽分為多種, 為了保證完整性和可維護(hù)性, 要把各個(gè)標(biāo)簽的正則分開寫, 也便于之后在分析每個(gè)片段的時(shí)候來取子匹配, 比如img標(biāo)簽的src, a標(biāo)簽的href.

經(jīng)過研究, 正則是不可以拼接的, 只有字符串可以拼接. 所以我們要把不同標(biāo)簽的正則寫成字符串, 再在需要的時(shí)候拼接. new RegExp(pattern)的pattern參數(shù)是可以接受字符串的.

匹配text的難題與正則匹配的動(dòng)作分析

眾所周知, 在html里的text是可以光禿禿的(在rn里必須加上Text標(biāo)簽). 那么如何匹配這光禿禿的東西呢, 我開始想了一個(gè)辦法: 因?yàn)閠ext都在標(biāo)簽之外, 也就是"夾在>和<中的字符", 或者在開頭(^)和<間的, 或者>和結(jié)尾($)間的. 結(jié)果標(biāo)簽全都匹配不到了.

原因是這樣的, 如果有"g"的模式, 匹配的過程是這樣的:

進(jìn)行第一次匹配, 匹配成功后把匹配部分排除待匹配內(nèi)容.

進(jìn)行第二次匹配, 匹配成功后把匹配部分排除待匹配內(nèi)容.

直到匹配失敗, 返回所有結(jié)果.

舉個(gè)例子:

"applebananaapple".match(/(apple|banana)/g)

結(jié)果是["apple", "banana", "apple"]

如果把banana的最后一個(gè)字母和apple的第一個(gè)字母寫成一個(gè):

"applebananapple".match(/(apple|banana)/g)

那么結(jié)果就是["apple", "banana"]了.

反而利用了這個(gè)特點(diǎn), 把text的正則寫成: 不包含<>/ ([^<>/]+), 并添加在最后一個(gè)匹配, 就能正確地匹配出text啦.

揭曉答案

寫得急促也許有遺漏, 最后貼上完成需求的代碼, 語言是rn, 在map輸出的時(shí)候帶著一些項(xiàng)目業(yè)務(wù)的邏輯請(qǐng)無視.

import React, {Component} from "react"
import {Text, View, Image, Platform, StyleSheet, TouchableOpacity} from "react-native"
import {ENVS} from "../../config/apiHost"

/*
    必須props: @html: html內(nèi)容
    可選props:  @style: 字體style; @magnifyImg: 顯示大圖
 */

const regex = {  // "_" for close tag
    p: `]*?>`,
    _p: `

`, span: `]*?>`, _span: ``, br: `
`, a: `]*?href=("|")([^>]+?)1[^>]*?>([^<]+?)`, // $1 是標(biāo)點(diǎn)符號(hào)用來處理匹配 $2 href的帶引號(hào)的內(nèi)容 $3 文件名(a標(biāo)簽的innerText), img: ``, // $1 標(biāo)點(diǎn)符號(hào) $2 src的內(nèi)容 text: `[^<>/]+`, // 匹配剩下的, 一定要放在最后 } const tobeRemoved = new RegExp(`(?:${[regex.p, regex._p, regex.span, regex._span, regex.br].join("|")})`, "g") const parseToAst = new RegExp(`(?:${[regex.a, regex.img, regex.text].join("|")})`, "g") export default class Parsed extends Component { render () { let str = this.props.html.trim() if (!str) { return ( html attr not passed to component "parseHtml" ) } matches = str.replace(tobeRemoved, "").match(parseToAst) return ( {matches.map((block, index) => { for (let [key, value] of Object.entries(regex)) { let res = new RegExp(value).exec(block) if (res) { if (key === "text") { return ( {block} ) } if (key === "a") { if (res[2].includes("files")) { // 判斷附件 if (/[jpg|png|jpeg]/i.test(res[3])) { // 判斷圖片 let imgId = res[2].match(/d+/)[0] return ( {this.props.magnifyImg && this.props.magnifyImg(ENVS.production.api_base_url + "/files/" + imgId)}} > ) } } } if (key === "img") { return ( {this.props.magnifyImg && this.props.magnifyImg(res[2])}}> ) } } } })} ) } }

原文地址

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94696.html

相關(guān)文章

  • Day06 - Fetch、filter、正則表達(dá)式實(shí)現(xiàn)快速古詩匹配

    摘要:正則表達(dá)式實(shí)現(xiàn)快速古詩匹配作者簡介是推出的一個(gè)天挑戰(zhàn)。數(shù)據(jù)匹配操作使用基礎(chǔ)參考文檔項(xiàng)目源碼分析正則找出匹配的詩句替換高亮的標(biāo)簽構(gòu)造值會(huì)返回帶搜索關(guān)鍵字的新數(shù)組。執(zhí)行對(duì)大小寫不敏感的匹配。 Day06 - Fetch、filter、正則表達(dá)式實(shí)現(xiàn)快速古詩匹配 作者:?liyuechun 簡介:JavaScript30 是 Wes Bos 推出的一個(gè) 30 天挑戰(zhàn)。項(xiàng)目免費(fèi)提供了 30 ...

    Warren 評(píng)論0 收藏0
  • Day06 - Fetch、filter、正則表達(dá)式實(shí)現(xiàn)快速古詩匹配

    摘要:正則表達(dá)式實(shí)現(xiàn)快速古詩匹配作者簡介是推出的一個(gè)天挑戰(zhàn)。數(shù)據(jù)匹配操作使用基礎(chǔ)參考文檔項(xiàng)目源碼分析正則找出匹配的詩句替換高亮的標(biāo)簽構(gòu)造值會(huì)返回帶搜索關(guān)鍵字的新數(shù)組。執(zhí)行對(duì)大小寫不敏感的匹配。 Day06 - Fetch、filter、正則表達(dá)式實(shí)現(xiàn)快速古詩匹配 作者:?liyuechun 簡介:JavaScript30 是 Wes Bos 推出的一個(gè) 30 天挑戰(zhàn)。項(xiàng)目免費(fèi)提供了 30 ...

    Carl 評(píng)論0 收藏0
  • Day06 - Fetch、filter、正則表達(dá)式實(shí)現(xiàn)快速古詩匹配

    摘要:正則表達(dá)式實(shí)現(xiàn)快速古詩匹配作者簡介是推出的一個(gè)天挑戰(zhàn)。數(shù)據(jù)匹配操作使用基礎(chǔ)參考文檔項(xiàng)目源碼分析正則找出匹配的詩句替換高亮的標(biāo)簽構(gòu)造值會(huì)返回帶搜索關(guān)鍵字的新數(shù)組。執(zhí)行對(duì)大小寫不敏感的匹配。 Day06 - Fetch、filter、正則表達(dá)式實(shí)現(xiàn)快速古詩匹配 作者:?liyuechun 簡介:JavaScript30 是 Wes Bos 推出的一個(gè) 30 天挑戰(zhàn)。項(xiàng)目免費(fèi)提供了 30 ...

    StonePanda 評(píng)論0 收藏0
  • Day12 - 鍵盤輸入序列的驗(yàn)證指南

    摘要:監(jiān)測(cè)字符串變化聲明字符串輸入變化的獲取對(duì)象更新顯示數(shù)據(jù)事件監(jiān)聽通過監(jiān)聽鍵盤輸入的變化,當(dāng)鍵盤彈起時(shí),調(diào)用函數(shù)。 (Node+Vue+微信公眾號(hào)開發(fā))企業(yè)級(jí)產(chǎn)品全棧開發(fā)速成周末班首期班(10.28號(hào)正式開班,歡迎搶座) 作者:?liyuechun 簡介:JavaScript30 是 Wes Bos 推出的一個(gè) 30 天挑戰(zhàn)。項(xiàng)目免費(fèi)提供了 30 個(gè)視頻教程、30 個(gè)挑戰(zhàn)的起始文檔和 3...

    joy968 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<