我正在嘗試撰寫一個正則運算式來提取 URL 組件。可以在此處找到語法:RFC 3986。
一些組件是可選的。到目前為止,我有:
(. )://((.*)@)?(. ?)(:(\d*))?/((.*)\?)?((.*)#)?(.*)
分解是:
(. )://匹配后跟的方案://。不是可選的。((.*)@)?匹配權限的用戶資訊部分。選修的。(. ?)匹配主機。不是可選的。這里有一個問題,該組也將匹配可選埠。(:(\d*))?應該匹配埠。/這和后面的一切都應該是可選的。((.*)\?)?匹配路徑部分。選修的。((.*)#)?匹配查詢部分。選修的。(.*)匹配片段部分。選修的。
我怎樣才能改進這個正則運算式,使其成為 RFC3986-valid ?
有趣的事實:這個正則運算式匹配自己。
示例 URL(取自 RFC):foo://example.com:8042/over/there?name=ferret#nose
編輯:我忘了逃跑d。現在剩下要做的就是使主機后面的所有內容都是可選的,包括前導的/.
uj5u.com熱心網友回復:
如果您只是轉義斜杠,最好是冒號,您的正則運算式就可以正常作業。結果是(. )\:\/\/(.*@)?(. ?)(:(\d*))?\/((.*)\?)?((.*)#)?(.*)。下面是一個簡單的腳本,展示了如何使用它來過濾掉無效的 URI:
更新 根據評論我做了以下修改:
- 我已經添加了
(\:((\d*)\/))?(\/)*. 解釋:\:((\d*)匹配冒號,然后匹配任何數字字串。\/after this 匹配應該在這個數字字串之后的斜杠。這是因為埠不能包含除數字以外的任何其他字符。因此在 uri 的埠部分中找不到它們。- 最后,整個埠匹配運算式是可選的,因此
?. - 最后一部分表示許多或沒有斜線可以跟隨現有/不存在的埠
最終正則運算式:
(. )\:\/\/(.*\@)?(. ?)(\:((\d*)\/))?(\/)*((.*)\?)?((.*)\#)?(.*)
const myRegEx = new RegExp("(. )\:\/\/(.*\@)?(. ?)(\:((\d*)\/))?(\/)*((.*)\?)?((.*)\#)?(.*)", "g");
const allUris = [
/*Valid*/ "https://[email protected]:5050/page?query=value#element",
/*Valid*/ "foo://example.com:8042/over/there?name=ferret#nose",
/*Valid*/ "foo://example.com",
/*Not valid*/ "www.example.com"];
const allowedUris = allUris.map(uri => {
// Use the regexp to match it, then return the match
const match = uri.match(myRegEx);
return match;
});
console.log("Here are the valid URIs:");
console.log(allowedUris.join("\n\n")); // Should only print the first two URIs from the array.
uj5u.com熱心網友回復:
我找到了一種更好的方法來處理這個問題,同時也不會破壞捕獲組。
(\w[\w\d\ \.-]*)://(. @)?([^:/\?#] )(:\d )?(/[^\?#]*)?(\?[^#] )?(#.*)?
分解:
(\w[\w\d\ \.-]*)://根據 RFC-3986,匹配有效方案。(. @)?匹配用戶資訊;即直到@,可選的一切。([^:/\?#] )匹配主機;即遇到:或/或?或之前的一切。#(:\d )?匹配埠;即所有數字,可選(/[^\?#]*)?匹配路徑;即可/選地加上每個字符,直到遇到?或,可選地。#(\?[^#] )?匹配查詢;即?加上#遇到的每個字符,可選。(#.*)?匹配片段;即#加上之后的所有內容,可選。
編輯:我正在使用的最終版本(添加捕獲組以更好地提取 丟棄換行符):
(\w[\w\d\ \.-]*)://((. )@)?([^:/\?#\r\n] )(:(\d ))?(/([^\?#\r\n]*))?(\?([^#\r\n]*))?(#(.*))?
針對隨機生成的 url在線嘗試。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/458935.html
