2017年7月24日 星期一

重複attr合併的正規法要如何寫

重複attr合併的正規法要如何寫
資料來源:
https://www.ptt.cc/bbs/Gossiping/M.1436303280.A.6E5.html

※ 引述《pk9058 (WhenSunTea)》之銘言: : 如標題 : regex:/(style[=]["](.*?)["]{2})/ig : HTML內容: : <div id="test" style="color:#FFF;" class="title_block" style="background:#000;" title="Hello"> : <span style="font-size:18pt;">標題</span> : </div> : 在 regexr.com 測試發現他會連同 h2 的style也包含... : 麻煩版上的大大幫小弟解惑,謝謝 不曉得您的意思是不是要找同一個元素裡的所有style標籤 如果是,那有兩種做法: 第一種作法比較簡單 可以單純只用一條Regex來找出「最後那個元素」的所有style標籤 而且所有程式語言都通 Regex的pattern如下: /(style=)('|\")[^'\"]*\2(?!(.|\n)*>(.|\n)*\1('|\")[^'\"]*\5)/gi 如下的程式碼會匹配到紅色字: <div id="test" style="color:#FFF;" class="title_block" style="background:#000;" title="Hello" style="font-size:16px;"> <input style="font-size:18pt;" disabled style="color:red;" name="inp" style="text-align:left;"> <span style="color:#F00;" style="font-family:arial;">ABC</span> </div> <div style="text-decoration:none;" id="test2" style="color:blue">333</div> 我來說明一下這條pattern: 第一個桃紅色部分的「(style=)」意思是匹配「style=」這個字串,這沒什麼學問。 第二個黃色部分的「('|\")[^'\"]*\2」意思是先匹配單引號(')或者雙引號(")1次,然後後面可能有一個或多個不是單引號或雙引號的字元,但也有可能沒接,然後再接跟第2個括號裡匹配的相同字元 (也就是如果你第一次輸入雙引號,這邊就必須也是雙引號,反之單引號亦然) 最後綠色部分的「(?!(.|\n)*>(.|\n)*\1('|\")[^'\"]*\5)」意思是這整個「style="..."」標籤的後面不能有大於符號(>)然後又接著出現「style="..."」或「style='...'」的字樣。 所以只要是最後一個元素的style標籤就通通可以match得到。 第二種就比較複雜麻煩了,必須要配合程式來做才行,而且不見得所有瀏覽器都支援這種方法: 第二種就可以像你所說的匹配「第一個元素」的所有style標籤 如果您是用Javascript寫 Regex的pattern如下: /[^>]*?(style=)('|\")[^'\"]*\2(?=[^>]*>[^>]*)/gyi 這裡我們用到了新的modifier:「y」(在舊瀏覽器,如IE可能不支援) 我來說明一下這個「y」好了 「y」是取「Sticky」的「y」來作為這個modifier的名稱 意思是:「只允許從開頭開始的連續匹配(如果「g」被設定則會連續),連續處是從上一個匹配的字的結尾處開始」 例如: /a/gy 這裡我們只可以匹配所有連續且從開頭開始的「a」 所以「aaassaaaa」只匹配到前三個「a」,後面的「a」則完全都匹配不到 另外像「mmmaaassaaaa」則所有的「a」都匹配不到。 回來上面的Regex pattern, 這行pattern的意思就是:如果「style="..."」或「style='...'」的前面都沒有任何大於符號(>) ([^>]*?),且後面又有出現大於符號(>) ((?=[^>]*>[^>]*)),然後又從開頭連續 (y modifier、g modifier),那麼就匹配 所以像下面這段原始碼會匹配到有底色的字: <div id="test" style="color:#FFF;" class="title_block" style="background:#000;" title="Hello" style="font-size:16px;" alt="test" style="text-shadow:none;"> <span style="font-size:18pt;" title="test1" style="text-decoration:none;" id="test1" style="font-family:arial;">ABC</span> <span style="color:blue;" style="font-weight:bold;">Hello!</span> </div> <div style="position:absolute;" class="test2" style="top:0;left:0;"></div> 但是這並不是我們要的結果, 我們只想要像「style="..."」這樣的標籤 所以就必須要用Javascript程式去擷取字串了。 程式如下: var str = "(原始碼...)"; var res = str.match(/[^>]*?(style=)('|\")[^'\"]*\2(?=[^>]*>[^>]*)/gyi); var result = res.map(function(s){ return s.substr(s.indexOf("style=")); }); 最後得到的陣列result就是我們想要的結果 ◎ 其中這裡的map就是對某一陣列一一做函數的處理。 如果您用第二種方法是用PHP寫的,那麼就把「y」改成「A」即可 「A」與「y」功能雷同,在此不再贅述。 以上。 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 118.160.30.43 ※ 文章網址: https://www.ptt.cc/bbs/Web_Design/M.1500790383.A.432.html ※ 編輯: banana2014 (118.160.30.43), 07/23/2017 14:46:39
CauseSam: 高手! 07/24 08:21
maiico: 很詳細 07/24 10:45
ian90911: 推優文 07/24 10:48
pk9058: 感謝大大的熱心回復 :) 07/24 22:44
pk9058: 目前小弟的寫法是先用下面這段regex來取得attr group 07/24 22:46
pk9058: style\s*=\s*['"]?([^'"]+)['"]?/ig 07/24 22:55
pk9058: 之後將它刪除,然後重建新的 style 07/24 22:56
pk9058: 這是我自己寫的正規表示法,如有錯誤希望大大可以指正小弟 07/24 22:58
pk9058: https://codepen.io/anon/pen/oeNdRZ 07/24 22:58
pk9058: 小弟熟讀您的文章後又學到新的一課,感謝大大的細心教導 07/24 23:39
推文自動更新已關閉

沒有留言:

張貼留言