@拉拉詢問於如何使用正則表達式替換<*>?關於抓取網址從超文本標記語言。 以下是三個建議答案的更多細節。 首先,免責聲明:這些示例都沒有正確解析 HTML,因此它們都可能找到不存在的 URL,而錯過其他實際存在的 URL。
/*
THIS IS NOT AN HTML PARSER
HTML parsers are hard to write. There are better ways.
Neither of these JSL ideas can properly skip comments or
many other HTML tags that should be skipped. They will
find things they shouldn't and miss other things they
should find. They've only been minimally tested on one site.
This code is presented as "how can I use contains() vs patmatch()
to efficiently work through a large string looking for something?"
The second example is FIVE TIMES FASTER and a LITTLE MORE ACCURATE.
The third example uses text explorer to grab links. I don't think
there is a pre-existing regex for the link text descriptions. It works
very similar to this code; it is NOT an HTML parser either.
If you can use python, you might want to investigate "beautiful soup".
I've not used it, but believe it addresses the "hard to write" issue.
*/
解析 HTML 的問題主要是找到匹配的開始和結束標記並查看它們之間的數據。 這裡介紹的所有 JSL 都可能被 HTML 功能所困擾。 但是,這可能已經足夠好了;做你自己的測試。 另請參閱美麗的湯這可能是一個更好的答案。
下面是 HTML 網頁的一個片段,顯示了一個帶有 URL(href= 部分)的鏈接( 標記)和一些將在頁面上可見的文本(討論部分)。
< a > tag with URL and Text< a > tag with URL and Text< a > tag with URL and Text< a > tag with URL and Text< a > tag with URL and Text帶有 URL 和文本的 標籤
目標是製作一個包含 URL 和鏈接文本的數據表,每行一個。 一個典型的網頁可能有 100 個左右的鏈接,並且有半兆字節的文本。 一慢的解決該問題的方法(未顯示)是編寫一個簡單的正則表達式,一次查找一個鏈接,從文本中刪除該鏈接,然後重複,直到找不到更多鏈接為止。 如果只有一兩個,那就太好了。 但如果可能有 100 個,那麼就會操縱和搜索幾百兆字節的數據。
更快的方法是搜索數據,始終向前移動,在找到鏈接時構建數據表。 第一個示例使用 contains() 函數,該函數具有第三個參數來指定起始位置。 Contains() 還返回找到的位置。 通過將起始位置更新到剛好超出找到的位置,contains() 可以有效地瀏覽文本,而無需備份或修改文本。
u = "https://community.jmp.com/t5/Discussions/bd-p/discussions";
txt = Load Text File( u );
// a link on a page has at least two parts:
// the URL and some descriptive text.
// <A ...="" href="https://community.jmp.com/url" ...="" target="_blank"> descripton </A>
// p1 p4 p5
// using contains and regex. "<A>", p1 + 3 ); // find the end of the opening tag
p5 = Contains( txt, "</A>", p4 + 1 ); // find the ending tag
if( p5 > p4, // as long as the end is not zero, we found one, see break() below
desc = Substr( txt, p4 + 1, p5 - p4 - 1 ); // the visible link description. Images can be here too.
desc = Regex( desc, "<[^>]*>", "", globalreplace ); // remove span, image, etc tags
linktext = Substr( txt, p1, p4 - p1 + 1 ); // <A href="https://community.jmp.com/" target="_blank">
hreftext = Regex( linktext, "href\s*=\s*(\!"|')(.*?)(\1)", "\2" );// use regex to get the href value
if( !Is Missing( hreftext ), // sometimes there isn't one
dt << addrows( 1 );
irow = N Rows( dt );
dt:link[irow] = hreftext;
dt:description[irow] = desc;
);
, // else
Break() // no more end tags. there is maybe a mess of javascript.
);
pos = Max( pos, p5 + 3 ); // advance past the one just found
);
stoptime = Tick Seconds();
dt << endDataUpdate;
Show( stoptime - starttime ); </A>
該代碼的核心是這一行
while( (p1 = Contains( txt, "<A></A>
它做了很多工作:它在第三個參數中使用 pos 來跳過任何先前的工作,它找到下一個開始鏈接標記的 什麼都沒找到,因此循環停止。 下一行
p4 = Contains( txt, ">", p1 + 3 );
搜索以 。 p4(見評論)指向那裡。 從 p1+3 開始,contains() 會查找 p1 之後的一個,而不是重新查找更早的出現位置。 下一行類似,尋找p4之後的結束標籤
p5 = Contains( txt, "", p4 + 1 );
p5 將指向結束鏈接文本的 標記。 許多(但不是全部)HTML 標記都是這樣工作的,開始標記不帶 / ,結束標記帶斜杠。 有時開始和結束標記是相同的,使用 ,但此 JSL 忽略了這種可能性。
if 語句確定是否找到了某些內容,如果是,則獲取如下描述
desc = Substr( txt, p4 + 1, p5 - p4 - 1 );
p4 和 p5 分別指向 > 和 <。所以p4+1是第一個描述字符,p5-p4-1是描述的長度。 下一行通過刪除嵌入標籤來清理描述
desc = Regex( desc, "<[^>]*>", "", globalreplace );
GlobalReplace 意味著正則表達式將找到該模式,盡可能多次地將該文本替換為空。 該模式匹配 <,後跟零個或多個不是 > 的字符,後跟 >,它可能是 
p1和p4(見註釋)是整個鏈接標籤位置; linktext 是包含許多不需要的位的鏈接標記。 hreftext 使用 regex() 只提取 href 引號或撇號之間的 URL。 正則表達式模式使用 backref \1 來確保尾隨撇號或引號與前導撇號或引號匹配。 正則表達式模式中的第一個左括號創建與“或”匹配的捕獲組(對於 \1)。 第二個左括號是匹配的捕獲組(對於 \2),不情願地向前移動到需要在分隔符之間匹配的位置。 第三個左括號是捕獲組 3;括號和分組並不是真正需要的。 結果 \2 只是 URL。