欧美成人午夜精品久久久,国产?V天堂一区二区三区,欧美精品va在线观看,亚洲一区二区三区免费在线观看,av无码精品一区二区久久,欧美性爱视频不卡一区三区,欧美乱人伦视频在线观看,国产一级牲交高潮

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

正則可視化調(diào)試工具Rea:解析器與回溯軌跡全解析

正則可視化調(diào)試工具Rea:解析器與回溯軌跡全解析 正則表達(dá)式這玩意兒寫(xiě)的時(shí)候感覺(jué)自己就是語(yǔ)言學(xué)家調(diào) bug 的時(shí)候又覺(jué)得自己像個(gè)算命先生。尤其面對(duì)那種一長(zhǎng)串(?...)、(?!...)、嵌套分組、堆了七八個(gè)量詞的老古董正則你很難說(shuō)清楚它到底在干什么、為什么這一段匹配上了、那一段又吞了字符。去年我就在這種狀態(tài)里憋了很久最后決定動(dòng)手寫(xiě)一個(gè)工具叫ReaRegular Expression Assistant。它的核心能力不是幫你“驗(yàn)證正則對(duì)不對(duì)”而是把正則從字符串到匹配結(jié)果的每一步都拆開(kāi)以語(yǔ)法樹(shù)、匹配軌跡、回溯路徑的方式攤在眼前。這篇文章就把 Rea 的設(shè)計(jì)思路、解析器實(shí)現(xiàn)、執(zhí)行引擎可視化以及我實(shí)測(cè)中踩過(guò)的幾個(gè)深坑完整梳理一遍。如果你也經(jīng)常被復(fù)雜正則困住或者想做一個(gè)類似的“看得見(jiàn)執(zhí)行過(guò)程”的開(kāi)發(fā)者工具這篇應(yīng)該能給你不少能直接用的方案。1. 為什么我動(dòng)手寫(xiě) Rea市面上沒(méi)有講清楚正則的調(diào)試工具1.1 正則難讀的本質(zhì)你不是不會(huì)寫(xiě)是看不到它的結(jié)構(gòu)很多人覺(jué)得正則難是因?yàn)橹苯影岩淮址?dāng)成了“規(guī)則本身”。但正則其實(shí)是一門(mén)微型語(yǔ)言它從用戶輸入到最終匹配至少要經(jīng)過(guò)兩層解釋第一層是字符串層也就是你肉眼看到的那串字符第二層是語(yǔ)法層它要把*、、{}、[]、()、^、$這些東西識(shí)別成量詞、字符組、分組、斷言第三層才是執(zhí)行層也就是用語(yǔ)法樹(shù)去和目標(biāo)文本做狀態(tài)匹配。問(wèn)題在于市面上絕大多數(shù)正則工具只給你輸入框、測(cè)試文本、匹配結(jié)果列表三個(gè)東西。你看到的是“匹配了”或者“沒(méi)匹配”但看不到匹配引擎在中間到底走了哪條路。比如這個(gè)很常見(jiàn)的密碼校驗(yàn)正則^(?.*\d)(?.*[a-z])(?.*[A-Z]).{8,16}$它能在大多數(shù)工具里正常工作但如果你想知道“為什么第二個(gè)斷言失敗”工具只會(huì)在原地轉(zhuǎn)一圈給個(gè)淡淡的“無(wú)匹配”。正則本身成了一個(gè)黑盒調(diào)試就變成了盲猜。Rea 想解決的就是這件事把黑盒打開(kāi)。它會(huì)把正則解析成語(yǔ)法樹(shù)按分組、量詞、斷言的邏輯層級(jí)展開(kāi)然后按執(zhí)行引擎的每一步把當(dāng)前匹配位置、捕獲組快照、嘗試過(guò)的分支、回溯跳轉(zhuǎn)都記錄下來(lái)最后在界面上用“步驟列表 文本進(jìn)度條 回溯連線”的方式回放。這樣一來(lái)正則不再是猜謎而是有跡可循的調(diào)試對(duì)象。1.2 一個(gè)案例說(shuō)明現(xiàn)有工具的不足我在某個(gè)日志清洗項(xiàng)目里遇到過(guò)一條線上規(guī)則^(?:[^,]),(\d{4}-\d{2}-\d{2}),(.*)$意圖是從逗號(hào)分隔的日志行里取出日期和剩余內(nèi)容。工具測(cè)試時(shí)規(guī)則是通的但到了生產(chǎn)里有一批行死活匹配不上。后來(lái)逐行看發(fā)現(xiàn)某些日志的時(shí)間字段里多了個(gè)空格比如2024-01-02 03:04:05更關(guān)鍵的是前面有個(gè)字段本身包含逗號(hào)導(dǎo)致[^,]把后面的結(jié)構(gòu)全打亂了。這種問(wèn)題用現(xiàn)成工具很難定位。你看到“沒(méi)匹配”三個(gè)字但到底是因?yàn)槿掌诟袷藉e(cuò)了、字段分隔符不對(duì)、還是分組量詞吃掉了不該吃的字符沒(méi)有執(zhí)行軌跡你只能繼續(xù)加日志、改正則、再測(cè)反復(fù)試錯(cuò)。Rea 的定位就是把這個(gè)調(diào)試過(guò)程從“試”變成“看”讓引擎每走一步都留痕。1.3 Rea 的目標(biāo)用戶和使用方式Rea 主要面向幾類人常年寫(xiě)復(fù)雜正則的后端、數(shù)據(jù)開(kāi)發(fā)需要在規(guī)則提交前快速確認(rèn)執(zhí)行路徑做爬蟲(chóng)、日志解析、網(wǎng)絡(luò)安全策略的工程師正則往往就是核心邏輯搞錯(cuò)一次就全線崩帶新人的團(tuán)隊(duì)可以把 Rea 當(dāng)教學(xué)工具展示什么是回溯、什么是零寬斷言、為什么貪婪匹配會(huì)“吞掉”后面的部分想自己實(shí)現(xiàn)迷你正則引擎的人Rea 的解析和執(zhí)行代碼本身就是一份可以拆著看的參考。它不是用來(lái)替代常規(guī)正則測(cè)試器的。常規(guī)工具負(fù)責(zé)“結(jié)果對(duì)不對(duì)”Rea 負(fù)責(zé)“為什么對(duì)、為什么錯(cuò)、瓶頸在哪”。在實(shí)際使用里這兩者配合起來(lái)效率最高。2. Rea 的架構(gòu)設(shè)計(jì)為什么我要自己寫(xiě)一個(gè)解析器而不是復(fù)用現(xiàn)成正則引擎2.1 四層架構(gòu)詞法層、語(yǔ)法層、執(zhí)行層、渲染層Rea 的整體結(jié)構(gòu)分成四層每一層職責(zé)單一數(shù)據(jù)傳輸方向也很明確。層級(jí)主要職責(zé)輸入輸出詞法層把正則字符串切成有意義的最小單元正則源字符串Token 數(shù)組語(yǔ)法層把 Token 按優(yōu)先級(jí)組裝成 ASTToken 數(shù)組語(yǔ)法樹(shù)節(jié)點(diǎn)執(zhí)行層用 AST 模擬正則匹配過(guò)程并記錄步驟AST 待測(cè)文本步驟記錄數(shù)組渲染層把 AST 和步驟記錄可視化步驟記錄 AST界面交互展示這樣分層的好處是每一層都可以單獨(dú)測(cè)試。詞法層不關(guān)心語(yǔ)法對(duì)不對(duì)語(yǔ)法層不關(guān)心文本匹配執(zhí)行層只關(guān)心狀態(tài)遷移渲染層只關(guān)心怎么把數(shù)據(jù)畫(huà)出來(lái)。后面我排查引擎行為不一致的問(wèn)題時(shí)基本都能快速定位到具體某層而不是整鍋粥一塊煮。2.2 為什么選 TypeScript 而不是 Python 后端 網(wǎng)頁(yè)前端一開(kāi)始我確實(shí)想過(guò)用 Python 做解析引擎再包一層 Web 接口前端用 Canvas 畫(huà)軌跡。但很快否了。原因有三個(gè)第一Rea 的核心交互發(fā)生在瀏覽器里從輸入正則到看到軌跡最好是在一個(gè)頁(yè)面內(nèi)完成不要有網(wǎng)絡(luò)往返。純前端的 TypeScript 方案最干凈打開(kāi)頁(yè)面即用也能直接做成離線工具。第二正則的方言差異很大。JavaScript 自己就有 ECMAScript 正則語(yǔ)義如果后端用 Python 的regex庫(kù)做解析那 Rea 展示的行為和用戶瀏覽器里的實(shí)際行為就會(huì)出現(xiàn)差異。干脆直接用 TypeScript 按 ECMAScript 語(yǔ)義實(shí)現(xiàn)一個(gè)小型引擎反而能讓“工具行為”和“用戶環(huán)境行為”保持更近。第三調(diào)試工具本身得容易調(diào)試。TypeScript 有完整的類型定義AST 節(jié)點(diǎn)的結(jié)構(gòu)、步驟記錄的數(shù)據(jù)結(jié)構(gòu)都可以用類型約束起來(lái)改起來(lái)不容易改出隱蔽的運(yùn)行時(shí)錯(cuò)誤。2.3 為什么不直接復(fù)用現(xiàn)成的解析庫(kù)社區(qū)里確實(shí)有很好的正則解析庫(kù)比如regexpp、regexp-tree這些能生成標(biāo)準(zhǔn) AST也省很多事。但我最終還是自己寫(xiě)了解析器。原因很實(shí)際現(xiàn)成庫(kù)給出的 AST 偏向“規(guī)范正確”但不太照顧“可視化友好”。Rea 的語(yǔ)法樹(shù)既要做結(jié)構(gòu)展示又要和執(zhí)行引擎的步驟一一對(duì)應(yīng)。我希望每個(gè)節(jié)點(diǎn)上都掛著stepIndex、capturesAffected這類執(zhí)行期信息還要在渲染時(shí)能給分組、量詞、斷言分別上色。自己生成 AST意味著我能完全控制節(jié)點(diǎn)類型和副作用標(biāo)注。當(dāng)然自己寫(xiě)解析器不是逞能。我的實(shí)現(xiàn)目標(biāo)很明確覆蓋 ECMAScript 正則的常見(jiàn)語(yǔ)法子集包括字符類、分組、命名捕獲、非捕獲分組、前瞻斷言、后顧斷言、量詞和分支就好。像復(fù)雜的vflag Unicode 集合運(yùn)算這種極少數(shù)用到的特性我直接選擇不支持并在界面上給出“暫不支持”的提示。與其做個(gè)半吊子支持不如明確邊界把核心路徑打磨穩(wěn)。2.4 執(zhí)行引擎的定位不是追求性能而是追求“可觀察”Rea 的執(zhí)行引擎不需要像原生 V8 正則引擎那樣快它的核心指標(biāo)是每個(gè)決策都要能記錄下來(lái)。所以我實(shí)現(xiàn)的是基于 AST 的遞歸回溯模擬器每個(gè)節(jié)點(diǎn)進(jìn)入、嘗試、成功、失敗、回溯都會(huì)產(chǎn)生一條步驟記錄。這種實(shí)現(xiàn)方式在很短文本上性能完全夠用。因此我在 Rea 里留了一條默認(rèn)保護(hù)線待測(cè)文本長(zhǎng)度超過(guò) 5000 字符或者步驟數(shù)超過(guò) 5 萬(wàn)步就停止執(zhí)行并給出提示。這個(gè)限制不是偷懶是考慮到瀏覽器渲染壓力同時(shí)也是為了讓用戶意識(shí)到一個(gè)正則跑出幾萬(wàn)步本身就是需要警惕的信號(hào)。3. 解析器實(shí)現(xiàn)從一串字符串到一棵語(yǔ)法樹(shù)3.1 詞法層先切出最小單元詞法層做的事情很簡(jiǎn)單把源字符串掃一遍根據(jù)當(dāng)前字符是不是\、是不是[、是不是(來(lái)切出不同類型 token。我定義的基礎(chǔ) token 類型大概是這樣的type TokenType | char // 普通字符 | escape // \d \w \s \n \uXXXX 等轉(zhuǎn)義 | classStart // [ | classEnd // ] | groupStart // ( | groupEnd // ) | charClassEnd? // 用不到 | quantifier // * ? { | alternation // | | anchor // ^ $ | lookahead // (? (?! 等 | lookbehind // (? (?!詞法需要特別注意轉(zhuǎn)義字符。比如\d應(yīng)該作為一個(gè)Escapetoken它的值是d類型是“數(shù)字類”\.也是一個(gè)Escapetoken但語(yǔ)義是“轉(zhuǎn)義后的點(diǎn)字符”。轉(zhuǎn)義后面跟著什么字符決定了這個(gè) token 到底代表一類字符還是代表一個(gè)普通字面字符這個(gè)判斷放到語(yǔ)法層再做會(huì)更清晰。3.2 語(yǔ)法層用遞歸下降處理優(yōu)先級(jí)正則的優(yōu)先級(jí)從高到低大約是原子字符、字符類、分組 量詞 連接順序拼接 分支|。因此我用了遞歸下降解析器四個(gè)方法互相調(diào)用class RegexParser { private tokens: Token[]; private pos: number 0; parse(): Node { const expr this.parseAlternation(); if (this.pos ! this.tokens.length) { throw new Error(Unexpected token at position ${this.pos}); } return expr; } private parseAlternation(): Node { const children [this.parseSequence()]; while (this.match(alternation)) { children.push(this.parseSequence()); } return children.length 1 ? children[0] : { type: Alternation, children, captures: [] }; } private parseSequence(): Node { const children: Node[] []; while (!this.check(groupEnd) !this.check(alternation) !this.isEnd()) { children.push(this.parseRepeat()); } return children.length 1 ? children[0] : { type: Sequence, children }; } private parseRepeat(): Node { const atom this.parseAtom(); if (this.check(quantifier)) { const q this.eat(quantifier) as QuantifierToken; return { type: Repeat, atom, min: q.min, max: q.max, greedy: q.greedy, }; } return atom; } private parseAtom(): Node { const token this.peek(); // 根據(jù) token 類型分別處理普通字符、轉(zhuǎn)義類、字符類、分組、斷言 } }這個(gè)結(jié)構(gòu)很經(jīng)典但對(duì)正則來(lái)說(shuō)有幾個(gè)容易寫(xiě)錯(cuò)的地方。最典型的是分組解析左括號(hào)(后面可能是?、?!、?:、?name、?、?!這些尾巴必須在同一層處理干凈。我把所有分組入口都集合在parseAtom里private parseGroup(): GroupNode { this.eat(groupStart); const start this.prevToken(); let type: GroupType capturing; let name: string | undefined; if (this.peek().type flag) { const flag this.eat(flag); if (flag.value ?:) type noncapturing; if (flag.value ?) type lookahead; // 肯定前瞻 if (flag.value ?!) type negativeLookahead; if (flag.value ?) type lookbehind; if (flag.value ?!) type negativeLookbehind; // ?name 要單獨(dú)解析 } const body this.parseAlternation(); this.eat(groupEnd); return { type: Group, groupType: type, name, body, // 捕獲組編號(hào)在整棵 AST 構(gòu)建完成后統(tǒng)一分配 }; }這里有一個(gè)非常容易踩的坑命名捕獲組(?name...)的前綴?和后顧斷言(?...)的前綴?只差一個(gè)字符。詞法層如果分開(kāi)處理必須做到最長(zhǎng)的匹配優(yōu)先。我在詞法掃描時(shí)看到?會(huì)把后面的字符一起拿到看第三個(gè)字符是、!還是別的。如果是或!就是后顧斷言否則就當(dāng)作命名分組開(kāi)始。3.3 捕獲組編號(hào)的分配時(shí)機(jī)正則里捕獲組編號(hào)有其固定規(guī)則按(在正則字符串中出現(xiàn)的順序編號(hào)從左到右遇到普通捕獲組就遞增。非捕獲組(?:...)不參與編號(hào)但后顧斷言、前瞻斷言里的捕獲組卻參與編號(hào)。Rea 的做法是先完整生成 AST然后做一次后序遍歷給分組節(jié)點(diǎn)統(tǒng)一分配捕獲組索引。索引分配的信息會(huì)保存在 AST 節(jié)點(diǎn)上執(zhí)行引擎在記錄捕獲組快照時(shí)直接讀取。這個(gè)設(shè)計(jì)避免了在解析過(guò)程中動(dòng)態(tài)編號(hào)造成的狀態(tài)混亂尤其當(dāng)分組嵌套很深時(shí)后序遍歷比邊解析邊編號(hào)要穩(wěn)得多。3.4 字符類內(nèi)部的“第二套語(yǔ)法”字符類[...]內(nèi)部和外部的語(yǔ)法規(guī)則完全不同。普通上下文里.就是任意字符就是量詞但在[]里大部分元字符都失去特殊含義只是加號(hào)本身-在中間是范圍連接符在首尾或轉(zhuǎn)義后是普通字符。^出現(xiàn)在[后面第一個(gè)位置表示取反出現(xiàn)在其他地方就是普通字符。Rea 的詞法層會(huì)單獨(dú)維護(hù)一個(gè)“字符類上下文模式”。進(jìn)入[后詞法不再識(shí)別量詞、分支、分組而只識(shí)別普通字符、轉(zhuǎn)義字符、范圍符號(hào)-、以及結(jié)尾的]。這樣函數(shù)雖然多了一個(gè)狀態(tài)分支但后續(xù)解析邏輯清爽很多。4. 可視化執(zhí)行引擎把回溯變成看得見(jiàn)的軌跡4.1 回溯的本質(zhì)是選擇點(diǎn)的撤銷回溯是正則引擎最核心、也最讓人頭疼的機(jī)制。很多人的概念是“匹配失敗了就回溯”其實(shí)回溯發(fā)生在“當(dāng)前路徑匹配不下去時(shí)回到最近一個(gè)還能選其他路的選擇點(diǎn)”。想理解回溯可以把正則匹配想象成走迷宮。你到了一個(gè)岔路口左邊墻上有標(biāo)記“這是分叉點(diǎn)”你選擇走左岔路。走了幾十米發(fā)現(xiàn)是死胡同于是退回到岔路口撿起沒(méi)走過(guò)的右岔路再走。回溯的成本不一定高但如果在同一個(gè)分叉點(diǎn)反復(fù)試、試完又回到上個(gè)分叉點(diǎn)、疊了好幾層量詞路徑數(shù)量就會(huì)爆炸。Rea 的可視化引擎核心就是記錄每個(gè)分叉點(diǎn)的“打開(kāi)/關(guān)閉”動(dòng)作。每當(dāng)一個(gè)節(jié)點(diǎn)嘗試一個(gè)分支就產(chǎn)生一條try步驟如果分支失敗就產(chǎn)生一條backtrack步驟。這樣用戶能看到引擎到底做了幾次選擇、每次選擇消耗了什么字符。4.2 步驟記錄器的數(shù)據(jù)結(jié)構(gòu)執(zhí)行引擎在遞歸回溯過(guò)程中會(huì)產(chǎn)生海量中間信息但如果全部記錄性能會(huì)很差。Rea 對(duì)記錄內(nèi)容做了取舍不記錄每一次字符比較而是記錄“節(jié)點(diǎn)級(jí)事件”。一個(gè)CharNode的比較只記錄一次成功或失敗一個(gè)量詞的每次重復(fù)循環(huán)都記錄為一次迭代一個(gè)斷言節(jié)點(diǎn)記錄其成功/失敗以及結(jié)束位置。核心步驟類型如下interface Step { type: enter | try | match | fail | backtrack | end; nodeId: number; // AST 節(jié)點(diǎn)唯一 id nodeLabel: string; // 便于展示的節(jié)點(diǎn)描述 position: number; // 進(jìn)入該節(jié)點(diǎn)時(shí)的文本位置 nextPosition: number; // 離開(kāi)該節(jié)點(diǎn)后的文本位置 captureSnapshot: CaptureSnapshot; // 當(dāng)前捕獲組快照 stepIndex: number; // 全局遞增步驟號(hào) depth: number; // 遞歸深度渲染時(shí)用來(lái)做縮進(jìn) }捕獲組快照不能每次都深拷貝整個(gè)對(duì)象那樣文本稍長(zhǎng)就會(huì)內(nèi)存爆炸。我采用了“按需記錄”的方式只在進(jìn)入捕獲組失敗、退出捕獲組、或者回溯發(fā)生時(shí)記錄當(dāng)前捕獲組狀態(tài)。每一步事件都帶一個(gè)引用指向“上一次發(fā)生了捕獲變化的快照”渲染層再按需合并出完整狀態(tài)。這個(gè)優(yōu)化在回放幾千步的匹配過(guò)程時(shí)非常關(guān)鍵。4.3 執(zhí)行器代碼骨架執(zhí)行器本質(zhì)上就是遍歷 AST 的遞歸函數(shù)。以一個(gè)簡(jiǎn)化版為例function tryNode(node: Node, pos: number, ctx: MatchContext): number | null { switch (node.type) { case Char: { const ok ctx.text[pos] node.value; recordStep(try, node, pos, ok ? pos 1 : pos, ctx); return ok ? pos 1 : null; } case Star: case Plus: case Repeat: { return tryQuantifier(node, pos, ctx); } case Sequence: { let cur pos; for (const child of node.children) { const next tryNode(child, cur, ctx); if (next null) { recordStep(backtrack, node, cur, cur, ctx); return null; } cur next; } return cur; } case Group: { if (node.groupType capturing) { ctx.captureStart(node.index); } const endPos tryNode(node.body, pos, ctx); if (node.groupType capturing endPos ! null) { ctx.captureEnd(node.index, endPos); } return endPos; } default: return null; } }注意這里Sequence一旦遇到子節(jié)點(diǎn)失敗直接返回失敗由上層決定是否回溯。真正選擇點(diǎn)的管理放在Alternation和Repeat節(jié)點(diǎn)里。比如Alternation需要依次嘗試每個(gè)子分支失敗后記錄一次backtrack再試下一個(gè)分支case Alternation: { for (const child of node.children) { const result tryNode(child, pos, ctx); if (result ! null) return result; recordStep(backtrack, node, pos, pos, ctx); } return null; }量詞的邏輯更麻煩。因?yàn)樨澙妨吭~會(huì)先盡可能多匹配匹配到上限后再逐漸讓出字符做后續(xù)匹配。這個(gè)“讓出字符”就是回溯在量詞上的表現(xiàn)。Rea 在tryQuantifier里用一個(gè)循環(huán)先按貪婪策略吞字符吞到吞不下為止然后把一次次的“吞入”和后續(xù)“回吐”都記錄下來(lái)function tryQuantifier(node: RepeatNode, pos: number, ctx: MatchContext): number | null { let count 0; let cur pos; const attempts: number[] []; while (count (node.max ?? Infinity) (node.min 0 || count node.min)) { const next tryNode(node.atom, cur, ctx); if (next null) break; attempts.push(cur); cur next; count; } // 貪婪時(shí)先嘗試?yán)^續(xù)多匹配 while (count (node.max ?? Infinity)) { const next tryNode(node.atom, cur, ctx); if (next null) break; attempts.push(cur); cur next; count; } // 回退嘗試減少重復(fù)次數(shù) while (count node.min) { if (node.min 0 || count node.min) { const rest tryNode(node.next, cur, ctx); // 簡(jiǎn)化真實(shí)的遞歸結(jié)構(gòu)需要掛載 next 指針 if (rest ! null) return rest; recordStep(backtrack, node, cur, cur, ctx); } count--; cur count 0 ? attempts[count - 1] : pos; } return null; }實(shí)際引擎里node.next不像上面這么簡(jiǎn)單因?yàn)?AST 是樹(shù)結(jié)構(gòu)處理量詞時(shí)需要把“匹配完重復(fù)內(nèi)容后的剩余部分”作為 continuation 傳入否則很難正確回溯。我在實(shí)現(xiàn)里給每個(gè)節(jié)點(diǎn)增加next指針結(jié)構(gòu)上變成一個(gè)“AST 鏈?zhǔn)?continuation”的組合執(zhí)行器在量詞回退時(shí)就能把當(dāng)前位置交給后續(xù)節(jié)點(diǎn)繼續(xù)嘗試。node.next這個(gè)概念是 Rea 能正確可視化回溯的關(guān)鍵。如果不做 continuation只靠遞歸返回值來(lái)回退那么一旦量詞內(nèi)部失敗上層就傻眼了根本不知道還有“少吞一個(gè)字符再試后續(xù)”這一條路。4.4 一個(gè)完整案例的回放拿a(b|c)*d匹配abccd來(lái)演示。這個(gè)正則的邏輯是先匹配a然后(b|c)*可以匹配零個(gè)或多個(gè)b或c最后匹配一個(gè)d。在 Rea 步驟列表里你會(huì)看到近似這樣的事件序列步驟事件節(jié)點(diǎn)位置說(shuō)明0enterSequence0進(jìn)入整個(gè)表達(dá)式1matchChara0 - 1成功消耗 a2enterRepeat (bc)*13tryGroup (bc)1 - 24tryGroup (bc)2 - 35tryGroup (bc)3 - 46tryGroup (bc)4 - 57backtrackRepeat (bc)*5 - 48matchChard4 - 5后續(xù) d 匹配成功9endSequence5整體匹配完成這里第 7 步就是關(guān)鍵。用戶從前到后看會(huì)覺(jué)得“明明文本第三個(gè)字符就是 d為什么引擎還要先吞掉再回退”因?yàn)檎齽t里的貪婪量詞在不了解后續(xù)節(jié)點(diǎn)的情況下只能先盡可能多吞吞到吞不動(dòng)了再交還。這個(gè)“交還”動(dòng)作就是回溯也是很多正則性能問(wèn)題的來(lái)源。通過(guò) Rea 的步驟列表新手能直觀看到*在*和后面如果還跟著其他必須匹配的內(nèi)容很容易出現(xiàn)“先多吃再吐出來(lái)”的現(xiàn)象。如果后續(xù)內(nèi)容很多回溯次數(shù)會(huì)呈指數(shù)級(jí)增長(zhǎng)。5. 實(shí)測(cè)中的坑正則語(yǔ)義和 Rea 表現(xiàn)不一致的五個(gè)修復(fù)5.1 斷言和普通節(jié)點(diǎn)對(duì)“當(dāng)前匹配位置”的處理完全不同剛開(kāi)始實(shí)現(xiàn)斷言時(shí)我的執(zhí)行器統(tǒng)一用“節(jié)點(diǎn)結(jié)束位置”來(lái)推進(jìn)position。這在普通字符、分組、量詞上沒(méi)問(wèn)題但碰到(?...)、(?...)就錯(cuò)了。斷言不會(huì)消耗字符它從左到右檢查內(nèi)部子表達(dá)式能不能匹配能匹配就返回成功但匹配位置始終保持在斷言開(kāi)始的位置。我第一次實(shí)測(cè)時(shí)發(fā)現(xiàn)a(?b)c匹配abc的時(shí)候Rea 展示的步驟是“a 之后斷言 b 成功c 直接從位置 2 開(kāi)始匹配”而斷言的內(nèi)部匹配“從位置 1 到位置 2 消耗了 b”也被記錄成了普通消耗。這就導(dǎo)致用戶看到的位置推進(jìn)和實(shí)際引擎行為對(duì)不上。修復(fù)方式是給斷言節(jié)點(diǎn)單獨(dú)立一條規(guī)則內(nèi)部執(zhí)行完成后位置必須恢復(fù)為斷言入口位置。Rea 的步驟記錄里還會(huì)額外標(biāo)記“零寬斷言不消耗字符”讓用戶一眼看懂為什么斷言里的 b 沒(méi)有影響后面的 c。5.2 捕獲組編號(hào)在非捕獲組和后顧斷言里的偏移正則里有一個(gè)新手極其容易寫(xiě)錯(cuò)的地方(?:...)不算捕獲組編號(hào)但前瞻/后顧斷言里的(...)要算。比如(?(a))\1中\(zhòng)1指的是前瞻里的捕獲組(?:(b))\2則是非法的因?yàn)榉遣东@組里即便有(b)編號(hào)也只會(huì)是 1不存在 2。Rea 的后序遍歷編號(hào)時(shí)只是在普通Group節(jié)點(diǎn)上遞增編號(hào)。但我一開(kāi)始把斷言內(nèi)部的Group和后顧斷言內(nèi)部的子表達(dá)式也統(tǒng)一編號(hào)了這導(dǎo)致(?(a))b的捕獲組編號(hào)和原生引擎不一致。測(cè)試時(shí)我拿一個(gè)帶后顧斷言的復(fù)雜正則一對(duì)一對(duì)比連續(xù)錯(cuò)了幾十步才意識(shí)到問(wèn)題。后來(lái)我把“編號(hào)分配”和“執(zhí)行路徑”分開(kāi)考慮只要 AST 節(jié)點(diǎn)是Group且類型為capturing無(wú)論它出現(xiàn)在斷言內(nèi)部還是普通分支都參與編號(hào)但執(zhí)行時(shí)斷言內(nèi)部的捕獲組快照要臨時(shí)保存斷言失敗時(shí)恢復(fù)原狀。這才能和原生語(yǔ)義保持一致。5.3 指數(shù)級(jí)回溯不能被當(dāng)成普通步驟Rea 做到一半時(shí)我拿(a)$配一個(gè)aaaaaaaaaaaaaaaaaaaaaaaaX。這個(gè)正則自己會(huì)跑出天文數(shù)字一樣的步驟因?yàn)閍可以分成很多組又可以讓每組重復(fù)多次幾乎每一種分組方式都要試一遍。如果引擎老老實(shí)實(shí)把所有步驟都記錄到數(shù)組里頁(yè)面直接卡死。這里我設(shè)置了一個(gè)非常務(wù)實(shí)的保護(hù)步驟數(shù)超過(guò) 50000 就中止執(zhí)行并且單獨(dú)標(biāo)記“檢測(cè)到疑似災(zāi)難性回溯”。用戶看到的現(xiàn)象不是普通的失敗列表而是一條醒目的警告當(dāng)前正則可能在更長(zhǎng)文本上導(dǎo)致嚴(yán)重性能問(wèn)題。這個(gè)警告本身就是調(diào)試結(jié)論遠(yuǎn)比“無(wú)匹配”三個(gè)字有價(jià)值。從實(shí)現(xiàn)上講50000 步的保護(hù)閾值并不是隨便定的。我實(shí)測(cè)過(guò)普通復(fù)雜正則在一個(gè)幾十字符的文本上通常只跑幾百到幾千步50000 足以覆蓋絕大多數(shù)正常場(chǎng)景超過(guò)這個(gè)數(shù)大概率是正則本身出了問(wèn)題。5.4 字符類中]和-的邊界沒(méi)有想象中簡(jiǎn)單我一開(kāi)始處理[]時(shí)過(guò)于想當(dāng)然在字符類里遇到]就結(jié)束遇到-就當(dāng)作范圍連接符。但實(shí)際測(cè)[]-]這種正則時(shí)徹底翻車。這個(gè)正則是匹配]或-兩個(gè)字符之一的。它的結(jié)構(gòu)是[開(kāi)始第一個(gè)字符是]但因?yàn)閉緊跟在[后面所以它不應(yīng)該被視為結(jié)束符然后-是普通字符最后一個(gè)]才是結(jié)束符。詞法層必須知道“當(dāng)前是不是緊跟在[或[^之后”。只有在跟在開(kāi)始位置的字符才是普通字符否則才會(huì)作為結(jié)束符處理。類似地[a-]里的-在結(jié)尾沒(méi)有構(gòu)成范圍也只是普通字符。這些邊界情況在正則文檔里只有一兩句話在 Rea 里卻是一整組測(cè)試用例。5.5 命名分組和反向引用的映射關(guān)系Rea 支持(?name...)和\kname。一開(kāi)始我把名字和編號(hào)映射關(guān)系存在一個(gè)全局 Map 里解析一個(gè)正則、清空一次。結(jié)果遇到命名分組在后顧斷言里、并且正則主體里還有同名分組時(shí)Map 被覆蓋了。雖然 ECMAScript 規(guī)范不允許同一個(gè)正則里出現(xiàn)重復(fù)的命名分組但執(zhí)行到斷言內(nèi)部時(shí)捕獲組狀態(tài)是嵌套的不能簡(jiǎn)單使用同一個(gè)對(duì)象。我最后改成每個(gè)捕獲組快照包含兩份信息一份是編號(hào)索引到字符串位置的數(shù)組另一份是名字到編號(hào)的 Map。斷言執(zhí)行時(shí)這兩份數(shù)據(jù)一起進(jìn)入獨(dú)立棧幀。這樣即使斷言內(nèi)部和外部都有命名分組回退時(shí)也不會(huì)互相污染。5.6 與原生正則行為對(duì)齊的驗(yàn)證方法做這個(gè)工具最大的風(fēng)險(xiǎn)是自己實(shí)現(xiàn)了一個(gè)“看起來(lái)挺對(duì)”的引擎但實(shí)際行為和瀏覽器里的new RegExp不一致。那 Rea 不但沒(méi)用還會(huì)誤導(dǎo)人。所以 Rea 里內(nèi)置了一組對(duì)照測(cè)試把用戶輸入的正則先交給原生RegExp執(zhí)行一次拿到結(jié)果同時(shí)讓 Rea 自己的引擎執(zhí)行再比較兩者的匹配區(qū)間、捕獲組內(nèi)容是否一致。不一致時(shí)Rea 會(huì)在界面右下角彈出一條“與原生行為不一致”的提示并標(biāo)出第一個(gè)出現(xiàn)差異的步驟位置。這個(gè)機(jī)制幫我在開(kāi)發(fā)階段發(fā)現(xiàn)了很多隱蔽問(wèn)題。比如$在 ECMAScript 里默認(rèn)只匹配到文本末尾但如果設(shè)置了多行模式它還會(huì)匹配換行符之前的位置比如\b的“單詞邊界”邏輯在中文文本里和英文文本里的表現(xiàn)完全不同。這些如果不做對(duì)照測(cè)試靠人眼很難發(fā)現(xiàn)。6. Rea 在實(shí)際項(xiàng)目里的用法日志巡檢和新人培訓(xùn)6.1 用步驟回放定位日志正則的誤判我們后端有一段時(shí)間日志告警規(guī)則老出問(wèn)題。有一條規(guī)則要過(guò)濾掉所有包含SECRET關(guān)鍵字的日志行正則寫(xiě)成了^(?!.*SECRET).*$這條正則單獨(dú)的匹配結(jié)果看起來(lái)沒(méi)錯(cuò)但它有一個(gè)隱藏性能問(wèn)題負(fù)向前瞻里有個(gè).*SECRET如果失敗后續(xù)的.*還要繼續(xù)跑。在幾萬(wàn)行的日志流上跑正則引擎的回溯開(kāi)銷會(huì)被放大。用 Rea 把一條幾百字符的日志樣本放進(jìn)去回放會(huì)看到步驟數(shù)到了幾千步。原因就是負(fù)向前瞻在每個(gè)字符位置都做一次“往后找 SECRET”的嘗試找不到再前進(jìn)一個(gè)字符重復(fù)執(zhí)行??吹竭@個(gè)軌跡之后我們把規(guī)則改成了先用indexOf做快速排除再在數(shù)據(jù)流里跑正則日志處理速度立刻上來(lái)一個(gè)數(shù)量級(jí)。Rea 不能直接替你優(yōu)化正則但老實(shí)地把每一步選擇攤開(kāi)來(lái)看優(yōu)化點(diǎn)會(huì)自己浮出來(lái)。6.2 在代碼評(píng)審和規(guī)則變更前做“執(zhí)行軌跡審查”以前評(píng)審正則改動(dòng)只能看 diff 里的正則字符串憑經(jīng)驗(yàn)判斷“這樣改應(yīng)該沒(méi)問(wèn)題”。有了 Rea 之后我們形成了一個(gè)小流程任何涉及復(fù)雜正則的改動(dòng)都要附帶一張 Rea 生成的步驟概覽截圖至少包括分支嘗試次數(shù)、最大回溯深度、捕獲組命中次數(shù)這幾個(gè)指標(biāo)。這樣做的好處是評(píng)審人不用逐字讀正則直接看數(shù)字就能判斷這次改動(dòng)是不是引入了新的性能隱患。如果一次改動(dòng)讓步驟數(shù)從 200 漲到 8000哪怕功能測(cè)試全過(guò)我也會(huì)打回去重新設(shè)計(jì)因?yàn)椴襟E數(shù)暴漲意味著后面文本一旦變長(zhǎng)引擎遲早卡死。6.3 拿 Rea 給新人講清楚“貪婪與懶惰”的區(qū)別我經(jīng)常拿 Rea 給組里新人演示貪婪量詞和懶惰量詞的區(qū)別。比如.*?這個(gè)經(jīng)典寫(xiě)法。很多測(cè)試器只告訴新人“懶惰量詞盡量少匹配”但說(shuō)不清“盡量少”到底是怎么做到的。在 Rea 里跑a.*?b匹配axxbyyb能看到引擎先讓.*?匹配零個(gè)字符然后立刻嘗試匹配b失敗于是回退讓.*?多匹配一個(gè)字符再嘗試匹配b……重復(fù)這個(gè)過(guò)程直到找到第一個(gè)能接上b的位置。這個(gè)逐步“擠牙膏”的過(guò)程在步驟列表里一目了然比任何文字說(shuō)明都直觀。6.4 可擴(kuò)展的方向從匹配軌跡到自動(dòng)生成解釋Rea 現(xiàn)在的核心是“展示軌跡”但后續(xù)可以往“解釋軌跡”方向走。語(yǔ)法樹(shù)已經(jīng)結(jié)構(gòu)化了執(zhí)行步驟也已經(jīng)標(biāo)注了節(jié)點(diǎn)語(yǔ)義完全可以再加一個(gè)自然語(yǔ)言生成模塊把“當(dāng)前位置嘗試匹配數(shù)字字符失敗回溯到量詞分支”翻譯成人話。如果能生成一句話“這個(gè)正則失敗在第 12 步因?yàn)榈?3 個(gè)捕獲組沒(méi)有匹配到預(yù)期格式”那才是真正的正則老師。另一個(gè)擴(kuò)展方向是正則簡(jiǎn)化。通過(guò) AST 分析出冗余的嵌套分組、重復(fù)的字符類、不可能匹配到的分支然后給出提示。這個(gè)方向有挑戰(zhàn)但對(duì)日常維護(hù)歷史正則的人來(lái)說(shuō)價(jià)值巨大。7. 最后分享一點(diǎn)使用經(jīng)驗(yàn)Rea 開(kāi)發(fā)到現(xiàn)在我自己最深的體會(huì)是正則調(diào)試工具真正的價(jià)值不在于“多炫”而在于“把不確定性變成確定性”。以前遇到一個(gè)復(fù)雜正則我習(xí)慣先猜猜錯(cuò)就再改改完再測(cè)循環(huán)往復(fù)。現(xiàn)在我會(huì)先把正則丟進(jìn) Rea看一眼它的執(zhí)行軌跡很多時(shí)候問(wèn)題根源就在前 50 步里。如果你也想做個(gè)類似的東西我建議從一個(gè)小得多的范圍開(kāi)始先支持字符、字符類、量詞、分組這四類把可視化做好再慢慢加斷言和反向引用。不要一上來(lái)就想著完整實(shí)現(xiàn) ECMAScript 全部特性否則大概率會(huì)被邊界情況拖死。再給一個(gè)小技巧Rea 的步驟記錄里我最??吹牟皇恰捌ヅ涑晒Α钡哪切┎襟E而是backtrack步驟?;厮菰蕉嗾f(shuō)明正則的“決策”質(zhì)量越差越值得優(yōu)化。一個(gè)正則如果回溯步驟超過(guò)總步驟的 30%基本就該重寫(xiě)了。這句話扔給團(tuán)隊(duì)里的新人比講十分鐘理論都好用。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
婷婷久久综合| 91久久1118| 丁香五月天激情综合| 九九色人| 五月婷婷草| 色婷网| 欧美va亚洲va在线播放| 五月丁香六月久久| 99亚洲视频| 91丨九色丨熟女高潮| 五月丁香六月婷婷综合在线| 一二线视频 另类| 香蕉人在线香蕉人在线 | www.超碰97| 婷婷婷婷婷婷婷婷| 九九热视频思思| 丁香六月啪啪啪| 国产精品第一国产精品| www.日日夜夜.com| 日本色色色| 在线A色| 91男同| 国内久久婷婷| 丁香六月天婷婷色| 不卡在线视频| 国产人妻777人伦精品HD| 在线观看亚洲AV| 伊人超碰| 亚洲综合字幕色色| 综合五月婷婷| 亚洲精品国产成人AV在线| 久久久91精品| 美女婷婷激情亚洲| 久久久精品色色色| eeuus五月婷| 色五月天丁香婷婷色| 777米奇影视第四色| 五月天丁香成人| 五月婷婷丁香六月在线| 日日夜夜狠狠干| 插插插丁香五月婷婷| 丁香五月婷婷在线观看| 欧美成人精品A片免费一区99| 午夜免费试看| 欧美日本VA| 国产亚洲精品久久久久久牛牛| 婷婷另类小说| 182TV大香蕉| 九九热在线99| 99婷婷国产最新视频| 五月丁香在线偷拍视频| 五月天激情视频网站| 狠狠干总合| 99er这里只有精品| 九九热只有精品6| 五月婷婷黄色| 在线中文av| 五月久久婷婷天堂视频| 五月伊人网| 丁香六月婷婷综合啪啪| 色五月91| 婷婷五月丁香在线观看| 另类视频丁香五月| 激情五月婷黄版| 无套内射极品大美女| 婷婷五月天激情网站| 丁香五月欧美色综合| 99这里只有精品视频在线| 婷婷午夜| 久久香蕉网| 天天色天天搡| 激情综合自拍五月婷婷色五月| 久久婷婷五月丁香网| 吊色AV男人的天堂| 九九九九九无码| 天天爱天天日| 婷婷五月天小说网| 婷婷激情社区| 99视频综合| 久久久婷丁香五月| 日韩综合网络男女香蕉a片| 中文字幕av在线| 99爱爱网| 婷婷伊人五月天| 天天操综合网| 99爱精品| 超碰伊人碰婷婷五月| 香蕉伊人综合| 成人av在线电影| 亚洲色色色色色| 丁香婷婷人妻综合网| 五月丁香六月婷婷玖玖| 男人的天堂五月丁香| 五月婷婷六月丁香| 五月婷婷综合天天操| 日韩激情网站| 激情五月图| 婷婷99综合| 性欧美大战久久久久久久83| 人妻九九九九| 性爱视频99| 春色激情| 久久久久9久无码视频| 久久久久久久久久久44| 99热 免费| dingxiangtingtingliuyue| 色情五月综合婷婷| 91九九九九| 变态另类色图 | 欧美婷婷六月丁香综合色| 五月丁香猫咪久久婷婷综合视频激情四射网入口 | 久久精品婷婷| 影音先锋人妻出差| 婷婷丁香五月天激情| 黄色片久久| 欧美69色| 久久狠狠欧美| 秋霞AV淫| 五月丁香久久激情综合| 久久久久久久久久久久久久人妻视频| 欧美成人猛片AAAAAAA| 波多婷婷久久| 丁香六月婷婷综情欧美| 五月天激情综合| 另类天堂| av免费在线网站| 九九热再线九九视频免费在线观看 | 五月丁香A片| 丁香五月冃欧美| 色五月天电影| 国产91视频| site:xiongshengzz.com| av婷婷丁香 六月| 99热免| 99热在线观看精品| 日本久久超碰| 丁香五月天论坛| 色婷婷综合视频| 婷婷综合九月| 久久这里有精品视频| 精品久久久人妻| www.金莲av| 精品久久99码| 婷婷五月AV| 婷婷亚洲在线| 色色丁香五月婷婷| 丁香六月婷婷综合| 深爱五月激情网| 另类 在线| 色婷婷色五月另类综合| 日韩成人av在线| 丁香亚洲色综合| www.夜夜操.con| 噜噜操操| www.99热这里精品| 欧洲亚洲精品| 久久香蕉婷婷| 色婷另类| 91精品婷婷国产综合| 久久性爱视频这里只有精品| 人人操9| 九九大香视频| 噜噜五月天综合| 色婷婷综合网| AV九九| 9色视频在线| 五月天六月色| 99手机在线精品视频| 欧美色五月天| 七月激情六月婷婷综合在线播放| 中文AV网| 中文字幕综合| 久久精品99| 色色色色色日韩午夜激情 | 色综合色色色色| 天天日婷婷| 天天狠狠夜夜狠狠2023| 五月六月婷婷激情网| 伊人久久五月天| 二级黄色毛片| 99色视频| 亚洲激情网| 中文字幕黄色片| 久久久噜噜噜久久人妻| 婷婷99狠| 丁香午夜天| 五月天激情黄色网址| 成人性爱精品视频| 麻豆忘忧草午夜| 日日夜夜狠狠干| 91国产精品视频播放| av国产精品| 丁香六月色婷婷欧美| 色色热| www.热99热| 97偷拍在线视频| 丁香五月综合激情啪啪| 在线VA视频| AV片在线观看| 99久久激情视频| 国产色婷婷亚洲| av婷婷六月丁香社区在线观看| 乱轮A片| 97爱综合| 欧美日韩二区在线| 播五月丁香六月| 久久综合婷婷激情| 99热免费精品| 99热这里有精品24| 久久婷婷五月综合激情国产| 天天做综合| 天天日天天插| 79精品视频在线观看,| 日本三级毛片| 男女啪啪做爰高潮无遮挡| 丁香五月天激情综合网| 99啪啪网| 国产午夜精品AV一区二区麻豆| 久九色| 超碰天堂网| 天天操加勒比| 99久久6| 91热视频色网站| 婷婷射丁香| 色色五月天网站| 九九色逼| 久久婷婷六月综合| www.25五月婷婷| 深夜婷婷 丁香| 天天日天天摸| 婷婷成人丁香色情基地30 | 一区二区无码视频| 五月天.com| 操熟女成人网| 五月天色综合| 五月天婷婷7米| 6080av| 99热免费精品| 亚洲另类婷婷五月综合| 99热久久这里只有精品| 五月天婷婷色色| 婷婷色爱| 插插干干干色| 91色五月| 人操91在线| 99九九视频| 九月丁香五月婷婷| 九九综合九九| 成人色图情色成人网 www.5b5b5bcom 五月天 | www.99在线| 深爱激情av| 激情玖玖sh| 日韩啊啊啊| 97资源欧美日韩大香蕉超碰一区| 五月天久久婷婷| 色婷婷www| 五月天激情.com| 婷婷综合五月| 婷婷99视频精品| 开心五月婷婷在线视频免费观看| 啪啪色激情五月天| 狠狠色噜噜狠狠狠狠综合| 五月天婷婷综合色| 亚洲亚洲人成综合网络| 婷婷大美在线| 色色色色综合网| 精品成人无码A片观看香草视频| 婷婷五月激情网| 丁香五月成人论坛| 大香蕉九九热| 国产亚洲99久久精品| 天堂爱啪啪| 人妻中文字幕网| 99人人干人人操| 婷婷五月天丁香久久| 九九综合色综合| 免费观看全黄做爰的视频 | 人人操人| 伊人激情网| www.97视频| 久久婷婷丁香| 色色五月天婷婷丁香| 五月丁香花婷婷玉莉AV| 九九热精品视频九九| 丁香六月婷婷久久综合八月| 激情图片亚洲| 丁香婷婷精品视频| 色五月婷婷一二| 天天插轮理| 亚洲激情精品| 亚洲无码成人| 亚洲无AV在线中文字幕| 色婷婷五月天无码视频| 婷婷五月天激情在线| 狠狠色色综合| 久久婷婷网站| 91在线视频综合| 五月综合丁| 色综合中文综合网| 亚洲另类毛片| 丁香五月婷婷久久久| 影音先锋男人站,影音先锋男人色资源网,影音先锋AV最新资源站,影音先锋AV资源 | 五月天激情无码| 99热色无码| 思思热热久久| 91九色精品熟女内射| 色欲丁香| 美女被肏网站在线看| 99热99美国在线观看| 久久视屏这里只有久久| 99视频在线观看网址| 激情综合五月| 五月丁香啪。| 97碰成超视频免费视频| 91在线日本| 久久99精品日本| 日韩高清成人| 婷婷爱综合| 激情五月综合ì香亚洲| 激情綜合W W W,激情五月天| 东京热免费视频| 久久免费精品小视频| 6月丁香婷婷| 婷婷激情五月天7| 婷婷人妻激情| 九九蜜臀精品| 超碰av在线| 综合五月激情| 婷婷六月色播| 乱乱av| 9九热视频| www.婷婷.com| 天天爽天天摸| 99日本黄站| 日韩在线视频网站| 丁香六月婷婷| 中文字幕黄色电影网址| 99久久久| 热久久99热欧美国产亚洲| 五月婷婷免费视频| 在线观看亚洲视频影院| 国产精品久久久久久久久久| 超碰自拍天堂| 日本熟女视频一区二区| 五月天自拍网| 丁香婷婷啪啪| 色天使久久综合| 国产日批视频| 狠狠色综合网| 国内裸舞二区| 精品少妇人妻AV无码专区偷人 | 欧美性猛交99久久久久99按摩| 人人色人人弄人人操| 婷婷色五月天色| 这里只有视频精品| 亚洲乱码在线观看| 日韩五月婷婷久久| 再次出发二| 99爱爱网| 永久天堂日本| 爱草视频在线观看| 国产色色视频| 婷婷99狠狠躁天天躁中| 九九婷婷网五月天| www...com黄在线观看| 六月丁香花婷婷| 偷拍91九色| 久久婷婷五月综合激情国产| 五月婷婷片| 日本色道视频网站| 日本黄色一级| 久久天天| 婷婷五月天天爽| www,婷婷,com| 就爱啪啪婷婷| 丁香五月偷拍| 思思热闹这里只有精品| 国产无套精品一区二区| 久久婷婷久久| 激情五月天开心| 久久九九激情五月天 | 日日夜夜狠狠婷婷色| 人人操av| 日韩久久视频| 色欲av伊人久久大香线蕉影院| 综合网色| 五月综合激情网| 99热都是精品| 激情综合网之激情五月| 99热在线网站| 亚洲综合五月| 日韩二区搞逼插逼毛片| 青娱乐美女福利视频美臀| 爱射综合| 综合天天综合| 五月丁香六月婷| 欧美色图天堂网| 色婷久九| 色欲色天天香综合| 日韩啪啪视频| 国产亚洲色婷婷久久99精品91| 五月天色五月| 射区导航| 大香蕉婷婷五月天| 婷色五月天| 久久综合伊人综合在线| 久久人人九| 成人中文网| 热99在线精品| 激情网综合| 亚洲旡码| 五月婷婷97| 成人片在线播放| 色五月婷婷开心| 五月婷婷激情综合| 六月99天天婷婷激情综合| 性爱激情五月| 五月婷婷丁香瑟瑟视频| 色婷婷AⅤ| 亚洲熟妇无码乱子AV电影| 99re在线观看视频| 性按摩玩人妻HD中文字幕| 色五月天中文字幕| 亚洲mm免费| 26uuu| 激情伊人网| 日韩色五月| 日韩啪啪视频| 国产伦亲子伦亲子视频观看| 草做免费在线观看| 91精品综合久久婷婷九色| 99毛片| 天天性视频| 激情久久久| 天天操天天操| 一本色道久久综合狠狠躁小说| 91视频五月丁香| 久久五月视频| 秋霞av吧| 91日视频| 天天色综合色| 五月丁香888| 日本久热| 午夜九九电影| 久久在线大香蕉| 思思re99视频在线观看| 久久婷婷五月天激情| 野外99热| 久久色情| 天天干天天日天天操| 国产精品人妻欲求不满| 激情操逼婷婷| 大香蕉婷婷五月天| 五月丁香 啪啪啪| 99久久久久久久| 泰州成人视频| 婷婷婷婷色| 婷婷成人综合| 色色色色色九九九九九| 五月天另类视频| 久久66精品| 五月丁香花激情综合网| 精品亚洲国产成AV人片传媒| 日韩欧美成人片| 七七九九色色| 国产婷婷综合在线免费视频| 无码色| 日韩AAAAAAAAAAA片| 五月丁香六月在线欧美| av在线不卡播放| 天天色亚洲| 色色色色色爱| 99热只有精品综合| 丁香久久九九99| 久久99热这里只频精品6学生| 日韩色五月| 欧美va亚洲va| 色婷婷先锋| 国产精品激情AV久久久青桔| 婷婷永久在线| 亚洲第一第二网站| 丁香五月瑟瑟| 色婷婷导航| 91熟妇大香蕉| 亚洲V国产V欧美V久久久久久| 五月丁香婷婷视频| 六月色国内综合| 天天久久66xxx| se婷97| 人人摸人人| 天天操天天操天天操天天操天天操| 天天日天天狠狠操| 99精品视频偷拍| 在线观看视频1区| 99激情视频| 九九99热| 色色com| 欧美亚洲婷婷五月| 久久久久久xxxxx| 五月99久久| 影音先锋男人站,影音先锋男人色资源网,影音先锋AV最新资源站,影音先锋AV资源 | 天堂久久精品| 九九亚洲| 精品无吗va视频免费观看| 丁香五月婷婷丫| 色婷丁香| 婷婷九九| 外国碰视频网站97| 大香蕉久久婷婷精品综合| 99五月香婷婷丁香在线视频| 乱精品一区字幕二区| 99色在线视频| 国产激情视频在线观看| 久久综合五月天| h在线看免费版在线看| 丁香六月婷婷姐网| 日日撸日日操| 五月天婷婷黄色| 99激| 五月情综合| 青青草原中文字幕| 丁香六月婷婷激情综合| 色婷婷丁香网| 综合五月草| 亚州精品色情无码A片| 1024国产| 婷婷啪啪| 欧洲永久精品| 激情丁香五月婷| 色五月开心婷婷| 99久久久国产大片区| 97婷婷色| 激情六月丁香综合| 狠狠人人| 五月丁香六月婷婷免费视频| 五月婷AV| 五月天色影院| 激情爱爱网站| 六月婷婷色综合| 99热免费精品| 五月婷婷丁香六月| 色色欧美。| 婷婷五月天97干| 久cao香蕉影院| 天堂在线伊久| 五月花激情网| 人人操AV| www色婷婷久久综合久色| 久久er+| 狠狠操在线视频| 99色免费视频| 99视频激情四射| 六月丁香av| 婷婷在线视频| 超碰97在线操| 黄色毛片精品| 婷婷久久五月| 91啪级电影| 婷婷色爱| 狼人久草| 狠狠干五月| 韩国97天堂| 婷婷五月天AV在线| 日韩一区二区在线播放| WWW.色婷婷.COM| 丁香婷婷五月天在线视频| 色九月婷婷丁香| 色五月丁香网| 日韩成人不卡| 97人操人免费视频| 琪琪理论片| 久久性爰视频这里只有精品| 热五月婷婷| 色999亚洲人成色| 久久婷婷一级片| 婷婷丁香成人五月天| 看婷婷五月天网| 五月婷婷六月奇米网丁香| 99这里只有| 丁香五月天啪啪| 久操欧美在线观看97| 色五月中文字幕| 色情综合网| 99re在线这里只有精品视频首页| 五月激情婷婷综合| 最新无码专区| 五月丁香婷婷色色| 欧美激情凹凸丁香网| 久久久久激情| AV片在线观看| 久久五月天大美女| 五月天激情久久| 日本一级一级一级一级| 26uuu偷拍亚洲欧洲综合| 天天天久久久| 婷婷五月天小说| 亚洲乱码日产精品BD| 日韩美女羞羞网站在线观看| 思思久久96热在精品国产,| 久久男人网婷婷| 玖玖综合色| 五月花丁香婷婷| 色色日本| 六月婷婷色色色| 99在线视频在线观看| 伊人久久大香线蕉av最新| 香蕉97碰碰碰欧美| 婷婷五月丁香综合亚洲| 99无码视频| 欧美日本免费一道免费视频| 五月丁香婷婷啪啪| 五月婷婷激情| 色九月综合| 开心六月丁香五月婷婷| 91AV婷婷| 丁香六月成人网| 丁香激情六月天婷婷| 九色视频91| 激情啪啪五月天| 五月婷婷m| 色色性爱视频| 99玖玖免费视频| 婷婷丁香色五月| 精品一二三区久久AAA片| 久激情网| 激情丁香六月| 婷婷九月在线| 婷婷丁香五月激情| 开心五月婷婷伊人| 狠狠干伊人| 欧洲色| 91碰碰碰| 337p大胆噜噜噜噜噜91Av| 激情婷婷网| AAA亚洲AV| 成人午夜视频精品一区| 亚州激情在线视频| 五月天综合网| 97色色色色色色色| 久久机热/这里只有精品| 狠狠色丁香婷婷久久综合| 噜噜噜久久亚洲精品国产品91| 亚洲亚洲人成综合网络| 日本天天综合| 最近中文字幕大全免费版在线 | 深情六月婷婷综合久久| 久久99综合| 国产精品久久99| 五月天综合婷婷| 99在线视频精品| 九九这里是免费的视频5| 大香蕉七区| 六九色综合婷婷五月天| 婷婷丁香五月91| 色婷婷五月天| 色色五月天网站| 五月婷精品| 九色婷婷| 99热99色| 人人射av| 久久99大| 久久99热这里只有精品| 五月婷婷九| 991国产精选视频在线播放下载| 夜夜躁婷婷AV| 日本精品99网站| 久操大香蕉| 亚洲六月婷婷| 成人五月天在线视频在线观看| 久草热8精品视频在线观看| 婷婷六月网| 国产在线网| 精品A√| 五月伊人婷婷999| 成人免费高清在线播放| 色婷婷香蕉| 亚洲天堂热| 九月婷婷丁香| 婷婷色基地在线看| 成人五月天丁香| 天天色月| 激情五月四色| 蜜臀99精品| 久久伊人五月天| 国产99久久久国产精品免费看| 九色激情| 黄色一级影片| 蜘蛛女免费观看完整版高清电影| 九月丁香八月婷婷加勒比| 婷婷精品性视频| 婷婷五月天六点丁香五月| 开心激情婷婷| 婷婷伊人久久综合| 五月婷啪啪| 色欲久久综合| 天天日日综合| 91日韩在线| 爱爱网址9| 岛国av网站| 性日本激情| 香蕉曰比| 久久婷婷六月综合| 丁香丝袜五月| 日本一道久久| W色综合| 99狠狠色| 五月丁香六月婷婷婷婷| 五月婷啪啪| 成人片黄网站色大片免费毛片| 26UUU精品一区二区| 丁香婷婷精品视频| 激情五月九九九| 丁香五月天激情视频| 日日激情网| 婷婷色网站| 色五月色开心开心五月| 熟女激情五月天| 丁香六月婷婷综合啪啪| 婷婷五月天视| av无码电影| 香蕉人妻AV久久久久天天| 五月天婷婷爱| 国产精品激情五月天色婷婷| www超碰| 人碰人人人玩91| 五月丁香成人网| 色狠狠综合入口| 日韩砖区| 91视频精品99| 日韩精品VIP| 五月激情天| 九月婷婷激情| 九九精品视频在线观看| 亚洲色婷婷网站| 中文字幕综合| 超级碰碰碰久久网站| 午夜少妇在线观看视频| 色综合色五月| 永久精品| 夜夜做夜夜愛| 五月丁香六月婷婷免费| 99 热国产在| 波多野结衣AV无码Porn| www.婷婷五月.com| 日韩少妇内射免费播放| 97综合在线| 五月婷婷六月天| 99人人操人人操人人精| 五月婷婷久久爱| 欧美三级巜人妻互换| 五月叮香啪| 97色永久免费视频| 久久99热这里只有精品| 五月婷婷开心丁香| 色综合久久伊伊婷婷五月| 91婷婷丁香五月天免费视频网站| 六月色播| 成人综合视频在线| 999久久久国产精品| 丁香花五月天社区| 黄色激情网站在线观看| 日韩AV中文在线观看| 欧美经典片免费观看大全| 六月 丁香 视频| 六月婷婷综合激情| 综合激情五月婷婷| 狠狠色丁香婷婷久久综合| 五月天婷婷成人| 欧美国产一区二区三区| 这里只有精品9| 久久久人人人妻丝丝丝| 亚洲国产精品成人va在线观看| 青青草a在线| 激情五月天婷婷久久久久久久久久久 | 婷婷五月a| 丁J香六月首页| 国产99久9在线+|+传媒| 五月婷狠狠| 狠狠色综合图片| 丁香花狠狠婷婷亚洲中文字幕| 五月天丁香久久综合 | 极品五月天| 丁香社区婷婷五月| 99热中文字幕久久| 野战毛片三一3| 五月丁香影院 | 日韩肏屄网| 丁香五月激情网| 婷婷五月丁香综合激情| 亚洲成人网在线观看| 天天操B| 婷婷激情五月| 色色色视频免费无码 | 99九九精品| 狠狠色噜噜狠狠狠888| 国产精品色色| 色综合婷婷| 亚洲操操操| 成人做爰高潮A片免费视频| A片试看50分钟做受视频| 大香蕉伊人丁香五月| 操碰99在线视频观看| 九九精品婷| 久久看婷婷| 开心婷婷中文字慕| 97色伦另类图片小说视频 | 久久婷婷九月国产精品| 涩婷婷视频快播人妻| 91丨九色丨老农村| 久久99视频| 丁香婷婷射| 免费观看欧美成人AA片爱我多深| 精品人妻在线| 色五月婷婷在线| 婷婷视频在线| 干一干xxxx| 伊人影音无码一区二区三区| 五月丁香在线国产| 五月丁香综合激情| 亚洲五月花| 久热一区| 99久精品| 秋霞学生妹一二级| 99久久大片| 成人AV在线电影| 日本欧美成人片AAAA| 九九激情| 热99国产精品| 思思久日精品视频| 玖玖色综合网| 黄网在线免费| 色五月天堂| 26uuu欧美亚洲日韩| 久婷婷色| 国外亚洲成AV人片在线观看| 中文字幕五月久久婷婷| 美女亚洲五月丁香| 五月丁香六月婷婷在线观看| 99热免| 99热97美女| 激情欧美婷婷| 亚洲色激情| 日韩色色视频| 99干在线| 影音先锋激情网| 啪啪 综合网| 中文字幕视频色婷婷| 欧美在线97| 九九久久综合网站| 五月色综合| 在线日韩av| 激情五月天婷婷久久久久久久久久久| 五月丁香六月婷婷久久| 精品久久99| 九九热精品99| 亚洲、热| 99热激情| 激情爱爱网站超大免费| 开心激情久久久久久久| 亚洲激情在线| 亚洲久艹| 色噜噜狠狠狠狠色综合久欧美| 丁香五月天无码AV| 色色色综合| 国产精品成av人在线视午夜片| 激情综合啪啪啪| 99综合网| 9999热免费视频视频| 久久成人性爱| 97干在线| 激情图片婷婷| 国产五月天欧美色| 婷婷不干网| 99视频这里只有免费精品| 婷婷色五月开心五月| 99ri网站在线观看| 五月激情另类| 五月婷婷在线视频| 久久婷婷国产| 亚洲激情另类| 91 久热| 青青草六月丁香| 婷色五月| 久久永久网址| 久热9| www激情网站| 丁香婷婷五月| 亚洲人成播放网站| 另类综合国产| 欧美槡BBBB槡BBB少妇| 熟女婷婷网站一婷婷五月一丁香婷婷一婷婷激情网 | 北条麻妃九九九国产精品视频| 欧美丁香婷婷天天操| www色五月| 操97免费超级视频| 尔尔AV一区| 狠狠色噜噜色狠狠狠综合色 | 夜夜人妻五月天| 婷婷开心激情| 少妇激情基地| 久久只有18视频| 五月丁香婷婷综合网| 性视频久久| 色五月婷婷综合在线| 天天干天天插| 色狠狠综合入口| 婷婷五月天小说| 九九精品99久久久| 婷婷丁香五月激情密臀av| 色五月自偷自拍婷婷婷婷| 婷婷五月天亚洲| 色婷婷啪啪| 美女五月狠狠| 国产亚洲99久久| 亚洲欧美婷婷五月色综合| 超碰色女人| 99热精品在线| 91Chinese在线| 91久热| AA丁香综合激情| se色99| 夜夜嗨一区二区三区直播内容 | 五月婷婷深深爱| 九月婷婷激情| 九久9精品| 丁香五月网站| 天天日夜夜| 囯产精品一品二区三区| 五月天激情亚洲| 天天摸天天舔天天天天爽| 激情綜合網址| 五月丁香婷婷色| 狠狠88综合久久久久噜噜噜| 高潮毛片又色又爽免费| 日本va欧美va欧美| 一区二区三区XXXXXX| 久久永久视频| 综合五月丁香久久| 影音先锋日本三级资源| 午夜丁香五月天综合| 人人操操| 久久这里只精品| 人人添人人| 久久资源综合| 91碰在线| 天干天天干天天天天天| 久久久久9久无码视频| 五月丁香啪啪| 91狠狠综合久久久久久| 亚洲第一成人无码A片| 婷婷草| 激情综合九月| 夜夜穞天天穞狠狠穞AV美女按摩| 欧美婷婷五月| 玖玖在线视| 亚洲精品又粗又大又爽A片| 99性爱视频网站| 曰曰久久| 思思9久久| 真实亲子乱子伦高清在线观看| 九九99九九99| 成人网在线观看视频| 最新va在线播放| 激情五月第四色| 色婷婷aV四虎| 天天色天天日| 97丁香五月| 欧美噜噜噜草| 婷婷六月成人| 久久9久| 伊人婷婷五月| 中文精品在| 欧美色片中文字幕久久久久| 婷婷五月精品中文字幕| 丁香五月天天日| 激情五月综合第一页| 无码少妇高潮喷水A片免费| 五月天开心色情网| 国产FREESEXVIDEOS性中国| 天天干天天干天天操| 色五月婷婷天天干| 日本久久9| 被男人添B超爽视频| 六月婷婷激情| 六月香五月婷| 九热精品| 大香蕉网 久久| 99无码视频| 国产欧美va| 亚洲AV无码久久精品色欲| 1024婷婷综合久久五月天| 日本eVa一区=区视频| 久热大香蕉| 午夜做爱影院| 婷婷亚洲五月丁香综合在线| 丁香婷婷色色| 日本波多野结衣视频| 99精品在线| www热久久yy9| 婷婷五月图片小说视频| 综合欧美五月婷婷| 成人AV中文字幕| 色五月 婷婷, 大香蕉| 五月丁香六月欧美综合网站| 激情开心五月天| 米奇影视资源婷婷狠狠色激情欧美五月丁香 | 清纯唯美 激情四射| 婷婷五月激情五月激情| 婷婷丁香五月色| 午夜不卡成人一区二区| 欧美日韩99| 超级碰碰碰碰视频| 97操资源婷婷| 天天日日夜夜| 五月婷婷无码| 婷婷97碰碰| 开心婷婷五月天激情网| 丁香五月婷婷亚洲另类| 婷婷激情五月天天天开心| 婷婷九月亚洲| 69精品人人人人人人| 婷久久高清| 成人无码精品1区2区3区免费看| 香蕉久久国产AV一区二区| 天天爽天天操| 欧美成人性爱网| 婷婷五月骚厕所| 26UUU亚洲欧美| 99热99热在线观看| 婷婷啪啪| 五月婷婷六月丁香| 久久丁香五月婷婷| 久草五月婷婷| 182TV亚洲| 色婷婷色九月| 色婷婷情片| 亚洲精品中文字幕成人片| 31色区视频免费看| 婷婷五月天亚洲综合网| 97日本在线播放| 成人在线二区| 亚洲中字AV电影在线网站| 丁香五月天激情网| 久99久热只有精品国产99| 激情六月五月婷婷综合网| 77799热| 色五月丁香总合网| 99热国内| 夜夜天天久久婷婷| 久久五月婷综合网| 丁香五月狠狠综合欧美| 六月米奇色综合| 久久五月婷综合网| 天天综合天天玩夜夜玩天天玩夜夜玩 | 久久这里只有精品99| 亚洲精品午夜国产va久久成人| www.超碰在线| 亚洲综合色色色| 狠狠操狠狠插| 99无码| 超碰日韩成人| 五月九九综合| 婷婷五月丁香综合桃花色网| 日本三级网址| 五月婷婷色综图片| 日夜操B| sS丁香五月婷婷| 涩涩五| 五月之婷婷| 天天搞天天爽| 91大神操美女| 五月天婷婷久久视频| 97人人草| 婷婷五月天免费99| 伊人在线大香蕉网| 色色色色色综合| 久久性操| 五月天激日本色情在线| www.五月婷婷久久.com| 桔色成人在线| 丁香六月激情四射| 99无码视频| 亚洲 在线 另类| 人妻六月天| 综合网啪啪| 天天爽天天爽天天爽天天爽天天爽天天爽天天| 天天爱天天做天天舔| 五月综合六月婷婷| 99精品无码| 狠狠色狠狠操| 一本色道久久88加勒比| 99热99思午夜精品| 新97人人上人人| 色五月天天| 激情五月天激情五月天| 大香蕉精品视频| 久久AAAA片一区二区| 婷婷六月香| 久99久在线观看| 七七九九色色| 夜夜夜夜夜骑撸| 日韩成人电影AV| 超PEN精品在线| 黑人熟妇一区二区三区| 琪琪理论片| www.com五月天| 六月丁香激情网| 丁香五月婷婷av影院| 色婷婷a| 天天干天天日日| 激情五月色婷婷| 五月天激情视频| www:99热视频| 天天摸.天天mo| 激情五月,婷婷五月,丁香五月| 91玖玖| 日本三级99人妇网站| 色综合久久综合中文综合网| 丁香五月天AV在线| 99热综合在线| 狠狠草在线观看| 激情六月日韩| 丁香五月自拍| 久久精品噜噜噜成人A∨色欲 | 99九无网码| 久久99久久99精品,久国产,久久精品免费,99久在线,久久久久国产精品免费网站,9 | 97av在线视频| av第一二区| 五月 丁香 欧美| 婷婷伊人综合中文字幕| 中文字幕无线久必| 婷婷伊人网| 99热在线观看精品| 大香蕉综合在线| www.9797国产| 人人看人人草人人摸| 国产亚洲99久久精品| 九一九九黄色| 最新午夜理论片| 亚洲婷婷基地| 67久久| 九九热这里都是精品6| 99.N在线视频| 以及AA大片看看| 久久久婷| 激情五月丁香六月综合AVXXXX| 五月婷婷色播| 国产阿姨日皮艹逼内射视频 | 色婷婷五月天偷拍| 五月天开心激情综合网| 五月婷婷亚洲色图| 91小黄书网址在线观看| 五月婷在线观看| 26uuu国产色| 狠狠狠狠狠| 第四色色六月色综合| 亚洲色色色色色| 91视频一起草| 91九色在线观看免费| 97婷婷丁香五月天激情图片| 久久九九综合| 伦99热| 五月丁香AV在线| 国产99久久久国产精品免费看| 婷婷六月激情| 久久久人妻| 五月天堂六月丁香亚州中文字幕久久| 天天干天天日日| 五月天激情网站| 欧美日韩99| 另类综合激情| 久久综合网桃花| 色婷婷五月中文字幕在线dvd| 成人无码髙潮喷水A片| 综合欧美五月婷婷| 久久草大香蕉| 亚洲五月天婷婷| 久操97| 九九久久高清| 精品无吗va视频免费观看| 国产激情一区| 婷婷综合五月色播| 大香蕉220| 日日鲁鲁夜夜爽爽| 激情综合五月婷婷| 天天做天天爱天天日| 五月天婷婷激情小说电影| 97操视频| 色五月综合在线| 婷婷色婷婷| 六月丁香色色| 亚洲激情婷婷| 91精品婷婷国产综合| 人人操人人爰人人一天天碰夜夜拍夜夜爽-中国A级毛片天天看天天谢… | 成 人片 黄 色 大 片| 激情99。| 熟妇无码乱子成人精品| 欧美亚洲999| 中文成人在线| 26UUU亚洲欧美| 五月天福利影院导航| 五月婷丁香亚洲| 日本波多野结衣视频| 噜噜久| www.久9| 五月天激情四射网站| 婷婷九月综合| 99色在线观看| 激情丁香婷婷五月天| 国外亚洲成AV人片在线观看| 色婷婷色情| 久久久噜噜噜操操操| 激情五月天小说|五月天开心激情网|亚洲精品国产自在现线|黄色五月天 | 丁香成人五月天| 青青草原中文字幕| 91碰碰| 婷婷五月天激情综合深爱| 伊人喵咪a V| 夜夜干天天干| 日亚二欧美| 九九操操| 丁香五月丐人妻| 色色色色丁香| 激情五月,婷婷五月,丁香五月| 丁香五月最新网址| 久久久久9| 天天搽天天射| 丁香五月婷婷激情97| 天天草天天摸| 丰满少妇乱A片无码| 色色丁香激情五月| 1区2区视频| 天天玩夜夜操| 六月天六月婷| 日本一级大片| 日本久久99| 五月丁六月香av| 狠狠色噜噜色狠狠狠综合色| 欧日韩成人| 婷婷久久久久久久| 九九无毛| 色婷操逼| 日本ww亚洲| 九九偷拍网| 久久伊人五月天| 五月丁香婷婷开心| 婷婷综合色| 婷婷不干网| 色综合九九| 婷婷色九月| 伊人五月久久| 欧美操逼天堂| 六月婷婷综合| 色五月综合在线| 五月天婷婷基地丁香| 亚洲日本三级片| 成人片在线播放| 五月色婷婷激情| 久久色五月| 久久一级AV| 亚洲性爱电影| 亚洲AV无码久久精品色欲| 9久久AV| 国产乱人偷精品人妻A片| 成人免费在线电影| 九九视频热|