【问题标题】:What is the best regular expression to check if a string is a valid URL?检查字符串是否为有效 URL 的最佳正则表达式是什么?
【发布时间】:2010-10-24 10:11:40
【问题描述】:

如何检查给定的字符串是否是有效的 URL 地址?

我对正则表达式的了解很基础,无法从我已经在网上看到的数百个正则表达式中进行选择。

【问题讨论】:

  • 任何 URL 或只是 HTTP?例如。 mailto:me@example.com 是否算作 URL? AIM 聊天链接?
  • 如果一个 URL 没有前导“http(etc)”,你如何能够将它与任何其他恰好有点的任意字符串区分开来?说“MyClass.MyProperty.MyMethod”之类的话?或者“我有时会错过空格键。这是个问题吗?”
  • 我已经添加了前缀'http://www.'在文本框之前。所以用户不需要输入'http://www.'并且应该只关心输入所需的 uri 名称。
  • 您使用什么编程语言?您可能不想重新发明轮子。
  • Microsoft 有一个包含 URL 表达式的正则表达式页面。当然是一个好的开始:msdn.microsoft.com/en-us/library/ff650303.aspx NB。以上页面已停用,但表中的表达式基本上仍然有效,可供参考。推荐的 URL 表达式(对我来说很好用)是:"^(ht|f)tp(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[ 0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+ &%\$#_]*)?$"

标签: regex url language-agnostic


【解决方案1】:

Javascript 现在有一个名为 new URL() 的 URL 构造函数。它允许您完全跳过 REGEX。

/**
 * 
 * The URL() constructor returns a newly created URL object representing 
 * the URL defined by the parameters. 
 * 
 * https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
 * 
 */
let requestUrl = new URL('https://username:password@developer.mozilla.org:8080/en-US/docs/search.html?par1=abc&par2=123&par3=true#Recent');

let urlParts = {
  origin: requestUrl.origin,
  href: requestUrl.href,
  protocol: requestUrl.protocol,
  username: requestUrl.username,
  password: requestUrl.password,
  host: requestUrl.host,
  hostname: requestUrl.hostname,
  port: requestUrl.port,
  pathname: requestUrl.pathname,
  search: requestUrl.search,
  searchParams: {
    par1: String(requestUrl.searchParams.get('par1')),
    par2: Number(requestUrl.searchParams.get('par2')),
    par3: Boolean(requestUrl.searchParams.get('par3')),
  },
  hash: requestUrl.hash      
};

console.log(urlParts);

【讨论】:

    【解决方案2】:

    最好的正则表达式是这里最好的答案的组合!哈哈哈!我刚刚测试了所有这些,并将最好的放在一起!我稍微改变了一下,只有一个捕获组!我能在这个页面的源代码中找到 637 个 URL!只有少数误报!

    ((?:(?:https?|ftp)://)(?:\S+(?::\S*)?@|\d{1,3}(?:\.\d{1,3}){3}|(?:(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)(?:\.(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)*(?:\.[a-z\x{00a1}-\x{ffff}]{2,6}))(?::\d+)?(?:[^\s]*)|(?:(?:(?:[A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::[0-9]+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)(?:(?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)|(?:(?:(?:(?:[A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)(?:(?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?))|(?:(?:(?:[\\w]+:)?//)?(?:(?:[\\d\\w]|%[a-fA-f\\d]{2,2})+(?::(?:[\\d\\w]|%[a-fA-f\\d]{2,2})+)?@)?(?:[\\d\\w][-\\d\\w]{0,253}[\\d\\w]\\.)+[\\w]{2,4}(?::[\\d]+)?(?:/(?:[-+_~.\\d\\w]|%[a-fA-f\\d]{2,2})*)*(?:\\?(?:&?(?:[-+_~.\\d\\w]|%[a-fA-f\\d]{2,2})=?)*)?(?:#(?:[-+_~.\\d\\w]|%[a-fA-f\\d]{2,2})*)?)|(?:https?:\/\/(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9])(?::?\d*)\/?(?:[a-z_\/0-9\-#.]*)\??(?:[a-z_\/0-9\-#=&]*)|(?:(?:(?:https?:)?(?:\/?\/))(?:(?:[\d\w]|%[a-fA-f\d]{2,2})+(?::(?:[\d\w]|%[a-fA-f\d]{2,2})+)?@)?(?:[\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,63}(?::[\d]+)?(?:/(?:[-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(?:\?(?:&?(?:[-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(?:#(?:[-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?)|(?:(?:https?|ftp)://(?:www\d?|[a-zA-Z0-9]+)?\.[a-zA-Z0-9-]+(?:\:|\.)(?:[a-zA-Z0-9.]+|(?:\d+)?)(?:[/?:].*)?)|(?:\b(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?\b))
    

    【讨论】:

      【解决方案3】:

      以下正则表达式适用于我:

      (http(s)?:\/\/.)?(ftp(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{0,256}\.[a-z] 
      {2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)
      

      匹配:

      https://google.com t.me https://t.me ftp://google.com http://sm.tj http://bro.tj t.me/rshss https:google.com www.cool.com.au http://www.cool.com.au http://www.cool.com.au/ersdfs http://www.cool.com.au/ersdfs?dfd=dfgd@s=1 http://www.cool.com:81/index.html
      

      【讨论】:

        【解决方案4】:

        我写了一个你可以运行的小版本

        它匹配以下网址(这对我来说已经足够了)

        public static void main(args) {
            String url = "go to http://www.m.abut.ly/abc its awesome"
            url = url.replaceAll(/https?:\/\/w{0,3}\w*?\.(\w*?\.)?\w{2,3}\S*|www\.(\w*?\.)?\w*?\.\w{2,3}\S*|(\w*?\.)?\w*?\.\w{2,3}[\/\?]\S*/ , { it ->
                "woof${it}woof"
            })
            println url 
        }
        
        http://google.com
        http://google.com/help.php
        http://google.com/help.php?a=5
        
        http://www.google.com
        http://www.google.com/help.php
        http://www.google.com?a=5
        
        google.com?a=5
        google.com/help.php
        google.com/help.php?a=5
        
        http://www.m.google.com/help.php?a=5 (and all its permutations)
        www.m.google.com/help.php?a=5 (and all its permutations)
        m.google.com/help.php?a=5 (and all its permutations)
        

        对于不以 httpwww 开头的任何 URL,重要的是它们必须包含 /?

        我敢打赌,这可以稍微调整一下,但它的工作非常好,因为它如此短而紧凑......因为你几乎可以将它分成 3 部分:

        查找以http开头的任何内容:

        https?:\/\/w{0,3}\w*?\.\w{2,3}\S*
        

        查找以www开头的任何内容:

        www\.\w*?\.\w{2,3}\S*
        

        或查找任何必须包含文本、点、至少 2 个字母和 ?/ 的内容:

        \w*?\.\w{2,3}[\/\?]\S*
        

        【讨论】:

        • 这不支持 URL 中的-
        【解决方案5】:

        对 URL 的简单检查是

        ^(ftp|http|https):\/\/[^ "]+$
        

        【讨论】:

          【解决方案6】:
          /^(http|HTTP)+(s|S)?:\/\/[\w.-]+(?:\.[\w\.-]+)+[\w\-\._\$\(\)/]+$/g
          

          通过测试检查演示:

          https://regexr.com/5cedu

          【讨论】:

            【解决方案7】:

            不管问的问题很广泛,我都会为将来寻找简单事物的任何人发布此内容...因为我认为验证 URL 没有适合所有需求的完美正则表达式,这取决于您的要求,即:就我而言,我只需要验证 URL 是否采用 domain.extension 的形式,并且我想允许 www 或任何其他子域,如 blog.domain.extension 我不关心 http(s),就像我的应用程序我有一个字段,上面写着“输入 URL”,所以很明显输入的字符串是什么。

            所以这里是正则表达式:

            /^(www\.|[a-zA-Z0-9](.*[a-zA-Z0-9])?\.)?((?!www)[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9])\.[a-z]{2,5}(:[0-9]{1,5})?$/i
            

            这个正则表达式的第一个块是:

            (www\.|[a-zA-Z0-9](.*[a-zA-Z0-9])?\.)? ---> 我们开始检查 URL 是否以 www.[a-zA-Z0-9](.*[a-zA-Z0-9])? 开头,这意味着一个字母或数字 + (anyCharacter(0 或多次) + 另一个字母或数字) 后跟一个点

            注意(.*[a-zA-Z0-9])?\.)?我们翻译成(anyCharacter(0 or multiple times) + another letterOrNumber) 是可选的(可以是或不是)这就是为什么我们将它放在括号之间并在后面加上问号?

            到目前为止我们讨论的整个块也放在括号之间,然后是?这意味着 www 或任何其他词(代表子域)都是可选的。

            第二部分是:((?!www)[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9])\. ---> 代表“域”部分,可以是任何以字母或数字开头的单词(www除外)+任何其他字母(包括破折号“-”)重复一次或多次,并以任何字母或数字结尾,后跟一个点。

            最后一部分是[a-z]{2,} ---> 代表“扩展名”,可以是任何字母重复2次或多次,所以它可以是com、net、org、art基本上任何扩展名

            【讨论】:

            • 不适用于仅包含 2 个字符的域。
            【解决方案8】:

            以下表达式适用于所有热门域。它将接受以下网址:

            此外,它还会以 url 作为链接发送消息
            例如please visit yourwebsite.com
            在上面的例子中,它会将yourwebsite.com 设为超链接

            if (new RegExp("([-a-z0-9]{1,63}\\.)*?[a-z0-9][-a-z0-9]{0,61}[a-z0-9]\\.(com|com/|org|gov|cm|net|online|live|biz|us|uk|co.us|co.uk|in|co.in|int|info|edu|mil|ca|co|co.au|org/|gov/|cm/|net/|online/|live/|biz/|us/|uk/|co.us/|co.uk/|in/|co.in/|int/|info/|edu/|mil/|ca/|co/|co.au/)(/[-\\w@\\+\\.~#\\?*&/=% ]*)?$").test(strMessage) || (new RegExp("^[a-z ]+[\.]?[a-z ]+?[\.]+[a-z ]+?[\.]+[a-z ]+?[-\\w@\\+\\.~#\\?*&/=% ]*").test(strMessage) && new RegExp("([a-zA-Z0-9]+://)?([a-zA-Z0-9_]+:[a-zA-Z0-9_]+@)?([a-zA-Z0-9.-]+\\.[A-Za-z]{2,4})(:[0-9]+)?(/.*)?").test(strMessage)) || (new RegExp("^[a-z ]+[\.]?[a-z ]+?[-\\w@\\+\\.~#\\?*&/=% ]*").test(strMessage) && new RegExp("([a-zA-Z0-9]+://)?([a-zA-Z0-9_]+:[a-zA-Z0-9_]+@)?([a-zA-Z0-9.-]+\\.[A-Za-z]{2,4})(:[0-9]+)?(/.*)?").test(strMessage))) {
              if (new RegExp("^[a-z ]+[\.]?[a-z ]+?[\.]+[a-z ]+?[\.]+[a-z ]+?$").test(strMessage) && new RegExp("([a-zA-Z0-9]+://)?([a-zA-Z0-9_]+:[a-zA-Z0-9_]+@)?([a-zA-Z0-9.-]+\\.[A-Za-z]{2,4})(:[0-9]+)?(/.*)?").test(strMessage)) {
                var url1 = /(^|<|\s)([\w\.]+\.(?:com|org|gov|cm|net|online|live|biz|us|uk|co.us|co.uk|in|co.in|int|info|edu|mil|ca|co|co.au))(\s|>|$)/g;
                var html = $.trim(strMessage);
                if (html) {
                  html = html.replace(url1, '$1<a style="color:blue; text-decoration:underline;" target="_blank"  href="http://$2">$2</a>$3');
                }
                returnString = html;
                return returnString;
              } else {
                var url1 = /(^|&lt;|\s)(www\..+?\.(?:com|org|gov|cm|net|online|live|biz|us|uk|co.us|co.uk|in|co.in|int|info|edu|mil|ca|co|co.au)[^,\s]*)(\s|&gt;|$)/g,
                  url2 = /(^|&lt;|\s)(((https?|ftp):\/\/|mailto:).+?\.(?:com|org|gov|cm|net|online|live|biz|us|uk|co.us|co.uk|in|co.in|int|info|edu|mil|ca|co|co.au)[^,\s]*)(\s|&gt;|$)/g,
                  url3 = /(^|&lt;|\s)([\w\.]+\.(?:com|org|gov|cm|net|online|live|biz|us|uk|co.us|co.uk|in|co.in|int|info|edu|mil|ca|co|co.au)[^,\s]*)(\s|&gt;|$)/g;
            
                var html = $.trim(strMessage);
                if (html) {
                  html = html.replace(url1, '$1<a style="color:blue; text-decoration:underline;" target="_blank"  href="http://$2">$2</a>$3').replace(url2, '$1<a style="color:blue; text-decoration:underline;" target="_blank"  href="$2">$2</a>$5').replace(url3, '$1<a style="color:blue; text-decoration:underline;" target="_blank"  href="http://$2">$2</a>$3');
                }
                returnString = html;
            
                return returnString;
              }
            }
            

            【讨论】:

              【解决方案9】:

              如果您想应用更严格的规则,这是我开发的:

              isValidUrl(input) {
                  var regex = /^(((H|h)(T|t)(T|t)(P|p)(S|s)?):\/\/)?[-a-zA-Z0-9@:%._\+~#=]{2,100}\.[a-zA-Z]{2,10}(\/([-a-zA-Z0-9@:%_\+.~#?&//=]*))?/
                  return regex.test(input)
              }
              

              【讨论】:

                【解决方案10】:

                改进

                检测如下 URL:

                正则表达式:

                /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/gm
                

                【讨论】:

                  【解决方案11】:

                  这是一个涵盖所有可能情况的好规则:端口、参数等

                  /(https?:\/\/(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9])(:?\d*)\/?([a-z_\/0-9\-#.]*)\??([a-z_\/0-9\-#=&]*)/g
                  

                  【讨论】:

                  • 这正是我想要的。
                  【解决方案12】:

                  我认为这是一个非常简单的方法。而且效果很好。

                  var hasURL = (str) =>{
                  	var url_pattern = new RegExp("(www.|http://|https://|ftp://)\w*");
                  	if(!url_pattern.test(str)){
                  		document.getElementById("demo").innerHTML = 'No URL';
                  	}
                  	else
                  		document.getElementById("demo").innerHTML = 'String has a URL';
                  };
                  <p>Please enter a string and test it has any url or not</p>
                  <input type="text" id="url" placeholder="url" onkeyup="hasURL(document.getElementById('url').value)">
                  <p id="demo"></p>

                  【讨论】:

                  • 你的正则表达式根本不起作用兄弟。它验证的只是您的字符串包含www 后跟one 字符(任何字符,因为您没有转义.)或http://https://ftp://并且任何这些可以后跟任何字母数字字符。因此,换句话说,以下所有字符串都将是有效的,但它们显然不是有效的 url:www.www▓£¢¤£¢¤www¢(参见 regex101)。您可以使用更短的正则表达式:(www.|(https?|ftp)://)\w*。 (顺便说一句,这仍然不是一个好的正则表达式)
                  • 显然是 www。 , www▓, £¢¤£¢¤www¢ 这些不是有效的网址。但我认为,那些也不是有意义的字符串。我只是尝试简化 url 模式。 @DrunkenPoney
                  • 我的目标不是编写 有意义的 字符串,而是表明奇怪的字符串会被接受,无论如何,因为你的正则表达式 validate for www我想您不一定需要指定协议,但您的正则表达式不允许像google.com 这样的网址。此外,我试图向您展示的问题之一是,您的正则表达式匹配字符串中的任何验证部分wwwhttp,...)。您至少可以指定您的字符串需要以它开头。
                  • 如果你想要一个快速的正则表达式来验证 url 但不是 100% 安全 here 是我用来从 url 中提取不同部分但可以用来验证一个string 包含 url 的基本部分。
                  【解决方案13】:

                  我编写了我的 URL(实际上是 IRI,国际化)模式以符合 RFC 3987 (http://www.faqs.org/rfcs/rfc3987.html)。这些都是 PCRE 语法。

                  对于绝对 IRI(国际化):

                  /^[a-z](?:[-a-z0-9\+\.])*:(?:\/\/(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:])*@)?(?:\[(?:(?:(?:[0-9a-f]{1,4}:){6}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|::(?:[0-9a-f]{1,4}:){5}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|v[0-9a-f]+\.[-a-z0-9\._~!\$&'\(\)\*\+,;=:]+)\]|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}|(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=])*)(?::[0-9]*)?(?:\/(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))*)*|\/(?:(?:(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))+)(?:\/(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))*)*)?|(?:(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))+)(?:\/(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))*)*|(?!(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@])))(?:\?(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@])|[\x{E000}-\x{F8FF}\x{F0000}-\x{FFFFD}\x{100000}-\x{10FFFD}\/\?])*)?(?:\#(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@])|[\/\?])*)?$/i
                  

                  也允许相对 IRI:

                  /^(?:[a-z](?:[-a-z0-9\+\.])*:(?:\/\/(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:])*@)?(?:\[(?:(?:(?:[0-9a-f]{1,4}:){6}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|::(?:[0-9a-f]{1,4}:){5}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|v[0-9a-f]+\.[-a-z0-9\._~!\$&'\(\)\*\+,;=:]+)\]|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}|(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=])*)(?::[0-9]*)?(?:\/(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))*)*|\/(?:(?:(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))+)(?:\/(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))*)*)?|(?:(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))+)(?:\/(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))*)*|(?!(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@])))(?:\?(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@])|[\x{E000}-\x{F8FF}\x{F0000}-\x{FFFFD}\x{100000}-\x{10FFFD}\/\?])*)?(?:\#(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@])|[\/\?])*)?|(?:\/\/(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:])*@)?(?:\[(?:(?:(?:[0-9a-f]{1,4}:){6}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|::(?:[0-9a-f]{1,4}:){5}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|v[0-9a-f]+\.[-a-z0-9\._~!\$&'\(\)\*\+,;=:]+)\]|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}|(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=])*)(?::[0-9]*)?(?:\/(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))*)*|\/(?:(?:(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))+)(?:\/(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))*)*)?|(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=@])+)(?:\/(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@]))*)*|(?!(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@])))(?:\?(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@])|[\x{E000}-\x{F8FF}\x{F0000}-\x{FFFFD}\x{100000}-\x{10FFFD}\/\?])*)?(?:\#(?:(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!\$&'\(\)\*\+,;=:@])|[\/\?])*)?)$/i
                  

                  它们是如何编译的(在 PHP 中):

                  <?php
                  
                  /* Regex convenience functions (character class, non-capturing group) */
                  function cc($str, $suffix = '', $negate = false) {
                      return '[' . ($negate ? '^' : '') . $str . ']' . $suffix;
                  }
                  function ncg($str, $suffix = '') {
                      return '(?:' . $str . ')' . $suffix;
                  }
                  
                  /* Preserved from RFC3986 */
                  
                  $ALPHA = 'a-z';
                  $DIGIT = '0-9';
                  $HEXDIG = $DIGIT . 'a-f';
                  
                  $sub_delims = '!\\$&\'\\(\\)\\*\\+,;=';
                  $gen_delims = ':\\/\\?\\#\\[\\]@';
                  $reserved = $gen_delims . $sub_delims;
                  $unreserved = '-' . $ALPHA . $DIGIT . '\\._~';
                  
                  $pct_encoded = '%' . cc($HEXDIG) . cc($HEXDIG);
                  
                  $dec_octet = ncg(implode('|', array(
                      cc($DIGIT),
                      cc('1-9') . cc($DIGIT),
                      '1' . cc($DIGIT) . cc($DIGIT),
                      '2' . cc('0-4') . cc($DIGIT),
                      '25' . cc('0-5')
                  )));
                  
                  $IPv4address = $dec_octet . ncg('\\.' . $dec_octet, '{3}');
                  
                  $h16 = cc($HEXDIG, '{1,4}');
                  $ls32 = ncg($h16 . ':' . $h16 . '|' . $IPv4address);
                  
                  $IPv6address = ncg(implode('|', array(
                      ncg($h16 . ':', '{6}') . $ls32,
                      '::' . ncg($h16 . ':', '{5}') . $ls32,
                      ncg($h16, '?') . '::' . ncg($h16 . ':', '{4}') . $ls32,
                      ncg($h16 . ':' . $h16, '?') . '::' . ncg($h16 . ':', '{3}') . $ls32,
                      ncg(ncg($h16 . ':', '{0,2}') . $h16, '?') . '::' . ncg($h16 . ':', '{2}') . $ls32,
                      ncg(ncg($h16 . ':', '{0,3}') . $h16, '?') . '::' . $h16 . ':' . $ls32,
                      ncg(ncg($h16 . ':', '{0,4}') . $h16, '?') . '::' . $ls32,
                      ncg(ncg($h16 . ':', '{0,5}') . $h16, '?') . '::' . $h16,
                      ncg(ncg($h16 . ':', '{0,6}') . $h16, '?') . '::',
                  )));
                  
                  $IPvFuture = 'v' . cc($HEXDIG, '+') . cc($unreserved . $sub_delims . ':', '+');
                  
                  $IP_literal = '\\[' . ncg(implode('|', array($IPv6address, $IPvFuture))) . '\\]';
                  
                  $port = cc($DIGIT, '*');
                  
                  $scheme = cc($ALPHA) . ncg(cc('-' . $ALPHA . $DIGIT . '\\+\\.'), '*');
                  
                  /* New or changed in RFC3987 */
                  
                  $iprivate = '\x{E000}-\x{F8FF}\x{F0000}-\x{FFFFD}\x{100000}-\x{10FFFD}';
                  
                  $ucschar = '\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}' .
                      '\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}' .
                      '\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}' .
                      '\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}' .
                      '\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}' .
                      '\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}';
                  
                  $iunreserved = '-' . $ALPHA . $DIGIT . '\\._~' . $ucschar;
                  
                  $ipchar = ncg($pct_encoded . '|' . cc($iunreserved . $sub_delims . ':@'));
                  
                  $ifragment = ncg($ipchar . '|' . cc('\\/\\?'), '*');
                  
                  $iquery = ncg($ipchar . '|' . cc($iprivate . '\\/\\?'), '*');
                  
                  $isegment_nz_nc = ncg($pct_encoded . '|' . cc($iunreserved . $sub_delims . '@'), '+');
                  $isegment_nz = ncg($ipchar, '+');
                  $isegment = ncg($ipchar, '*');
                  
                  $ipath_empty = '(?!' . $ipchar . ')';
                  $ipath_rootless = ncg($isegment_nz) . ncg('\\/' . $isegment, '*');
                  $ipath_noscheme = ncg($isegment_nz_nc) . ncg('\\/' . $isegment, '*');
                  $ipath_absolute = '\\/' . ncg($ipath_rootless, '?'); // Spec says isegment-nz *( "/" isegment )
                  $ipath_abempty = ncg('\\/' . $isegment, '*');
                  
                  $ipath = ncg(implode('|', array(
                      $ipath_abempty,
                      $ipath_absolute,
                      $ipath_noscheme,
                      $ipath_rootless,
                      $ipath_empty
                  ))) . ')';
                  
                  $ireg_name = ncg($pct_encoded . '|' . cc($iunreserved . $sub_delims . '@'), '*');
                  
                  $ihost = ncg(implode('|', array($IP_literal, $IPv4address, $ireg_name)));
                  $iuserinfo = ncg($pct_encoded . '|' . cc($iunreserved . $sub_delims . ':'), '*');
                  $iauthority = ncg($iuserinfo . '@', '?') . $ihost . ncg(':' . $port, '?');
                  
                  $irelative_part = ncg(implode('|', array(
                      '\\/\\/' . $iauthority . $ipath_abempty . '',
                      '' . $ipath_absolute . '',
                      '' . $ipath_noscheme . '',
                      '' . $ipath_empty . ''
                  )));
                  
                  $irelative_ref = $irelative_part . ncg('\\?' . $iquery, '?') . ncg('\\#' . $ifragment, '?');
                  
                  $ihier_part = ncg(implode('|', array(
                      '\\/\\/' . $iauthority . $ipath_abempty . '',
                      '' . $ipath_absolute . '',
                      '' . $ipath_rootless . '',
                      '' . $ipath_empty . ''
                  )));
                  
                  $absolute_IRI = $scheme . ':' . $ihier_part . ncg('\\?' . $iquery, '?');
                  
                  $IRI = $scheme . ':' . $ihier_part . ncg('\\?' . $iquery, '?') . ncg('\\#' . $ifragment, '?');
                  
                  $IRI_reference = ncg($IRI . '|' . $irelative_ref);
                  

                  2011 年 3 月 7 日编辑:由于 PHP 处理带引号的字符串中的反斜杠的方式,默认情况下这些是不可用的。您需要对反斜杠进行双重转义,除非反斜杠在正则表达式中具有特殊含义。你可以这样做:

                  $escape_backslash = '/(?<!\\)\\(?![\[\]\\\^\$\.\|\*\+\(\)QEnrtaefvdwsDWSbAZzB1-9GX]|x\{[0-9a-f]{1,4}\}|\c[A-Z]|)/';
                  $absolute_IRI = preg_replace($escape_backslash, '\\\\', $absolute_IRI);
                  $IRI = preg_replace($escape_backslash, '\\\\', $IRI);
                  $IRI_reference = preg_replace($escape_backslash, '\\\\', $IRI_reference);
                  

                  【讨论】:

                  • 如果您认为这很糟糕,您应该查看电子邮件:ex-parrot.com/~pdw/Mail-RFC822-Address.html
                  • @Gumbo,它在规范中被允许并用于 HTTP 应用程序的 URI 实现。不鼓励(出于显而易见的原因)但完全有效,应该预料到。大多数(如果不是全部?)浏览器有时会将 HTTP 身份验证转换为 URL 以供后续访问。
                  • @Devin,在什么语言的函数中?我用 PHP 编译它,但它可以在其他语言中使用。我应该用所有这些语言编写一个函数吗?或者,您也可以使用自己选择的语言来做同样的事情。
                  • @joshcomley 将 \x{ABCD} 替换为 \uABCD,如果你用 JS 编写的话
                  • 是的,http://com 是一个有效的 URL。 http://localhost 是,为什么不是其他词呢?您是正确的,u 修饰符在 PHP 中是必需的。我想明确一点,虽然我使用 PHP 生成了这些,但它们并不是特定于 PHP 的。
                  【解决方案14】:
                  ^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$
                  

                  现场演示:https://regex101.com/r/HUNasA/2

                  我已经测试了各种表达式来满足我的要求。

                  作为用户,我可以使用以下字符串点击浏览器搜索栏:

                  有效的网址

                  无效的网址

                  【讨论】:

                  • 测试这个 URL:Google.com URL 应该不区分大小写
                  • 在 URL 的末尾放置空格,然后再次输入符号/字母,它将被视为 URL 的一部分
                  • 缩短和更正/^(http(s)?:\/\/)?(www.)?([a-zA-Z0-9])+([\-\.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,5}(:[0-9]{1,5})?(\/[^\s]*)?$/gmregex101.com/r/KR2b6n/1
                  • 如果我用\b 替换^? 书挡,@AniNaslyan 的更正版本对我来说效果很好
                  • localhost 呢?
                  【解决方案15】:
                  https?:\/{2}(?:[\/-\w.]|(?:%[\da-fA-F]{2}))+
                  

                  您可以使用此模式来检测 URL。

                  以下是概念证明

                  RegExr: URL Detector

                  【讨论】:

                    【解决方案16】:

                    这是我制作的一个正则表达式,它从 URL 中提取不同的部分:

                    ^((?:https?|ftp):\/\/?)?([^:/\s.]+\.[^:/\s]|localhost)(:\d+)?((?:\/\w+)*\/)?([\w\-.]+[^#?\s]+)?([^#]+)?(#[\w-]+)?$

                    ((?:https?|ftp):\/\/?)?(组 1):提取协议
                    ([^:/\s.]+\.[^:/\s]|localhost)(组 2):提取主机名
                    (:\d+)?(group 3):提取端口号
                    ((?:\/\w+)*\/)?([\w\-.]+[^#?\s]+)?(groups 4 & 5):提取路径部分
                    ([^#]+)?(group 6 ):提取查询部分
                    (#[\w-]+)?(group 7):提取哈希部分

                    对于上面列出的正则表达式的每个部分,您可以删除结尾 ? 以强制它(或添加一个使其成为兼性)。您还可以删除正则表达式开头的^ 和末尾的$,这样就不需要匹配整个字符串。

                    regex101 上查看。

                    注意:这个正则表达式不是 100% 安全的,它可能接受一些不一定是有效 URL 的字符串,但它确实验证了一些标准。它的主要目标是提取 URL 的不同部分而不是对其进行验证。

                    【讨论】:

                    • 谢谢。这些答案的小组方法是最好的。希望按照下一页链接的this article 的方向进行更新,并对“不是 100% 安全”进行修订。对于大多数读者来说,像 99.9% 这样的量化就足够了。 :P
                    【解决方案17】:

                    我刚刚写了一篇博文,介绍了一个很好的解决方案,可以识别大多数常用格式的 URL,例如:

                    • www.google.com
                    • http://www.google.com
                    • mailto:somebody@google.com
                    • somebody@google.com
                    • www.url-with-querystring.com/?url=has-querystring

                    使用的正则表达式为:

                    /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/
                    

                    【讨论】:

                    • 那个也可以,但是它缺少对端口号的支持(在调试中很有用)。修改为/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&amp;=\+\$,\w]+@)?[A-Za-z0-9.-]+(:[0-9]+)?|(?:www.|[-;:&amp;=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&amp;;%@.\w_]*)#?(?:[\w]*))?)/
                    • 这个正则表达式不处理带括号的链接:例如msdn.microsoft.com/en-us/library/ms563775(v=office.14).aspx
                    • www后面的点不应该转义吗?
                    • 找到另一个匹配对象:width:210px;margin:3px
                    • 不匹配“example.com”...?
                    【解决方案18】:

                    现在这是一个相当古老的线程,问题要求使用基于正则表达式的 URL 验证器。我在寻找完全相同的东西时遇到了线程。虽然很可能编写一个非常全面的正则表达式来验证 URL。我最终选择了另一种做事的方式——使用 PHP 的 parse_url 函数。

                    如果无法解析 url,则返回布尔值 false。否则返回方案、主机等信息。这可能不足以单独进行全面的 URL 检查,但可以深入研究以进行进一步分析。如果目的是简单地捕捉拼写错误、无效方案等。这是完全足够的!

                    【讨论】:

                      【解决方案19】:

                      有趣的是,上面的答案都不能满足我的需要,所以我想我会提供我的解决方案。我需要能够做到以下几点:

                      • 匹配http(s)://www.google.comhttp://google.comwww.google.comgoogle.com
                      • 匹配 Github markdown 风格的链接,如 [Google](http://www.google.com)
                      • 匹配所有可能的域扩展名,如 .com、.io 或 .guru 等。基本上是长度在 2-6 个字符之间的任何内容
                      • 将所有内容分成适当的分组,以便我可以根据需要访问每个部分。

                      解决方案如下:

                      /^(\[[A-z0-9 _]*\]\()?((?:(http|https):\/\/)?(?:[\w-]+\.)+[a-z]{2,6})(\))?$
                      

                      这给了我上述所有要求。如有必要,您可以选择添加 ftp 和文件功能:

                      /^(\[[A-z0-9 _]*\]\()?((?:(http|https|ftp|file):\/\/)?(?:[\w-]+\.)+[a-z]{2,6})(\))?$
                      

                      【讨论】:

                        【解决方案20】:

                        非验证 URI 引用解析器

                        为了参考,这里是 IETF 规范:(TXT | HTML)。特别是,附录 B。解析使用正则表达式的 URI 引用演示了如何解析有效的正则表达式。这被描述为,

                        获取非验证 URI 引用解析器的示例,该解析器将采用任何给定字符串并提取 URI 组件。

                        这是他们提供的正则表达式:

                         ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
                        

                        正如其他人所说,最好将其留给您已经在使用的库/框架。

                        【讨论】:

                        • 完全没用。有人可以告诉我这个正则表达式 not 匹配的字符串吗? (“#?#?#”或“>>”都匹配。这些是什么类型的 URI?)
                        • @AlexD 不要向我抱怨。这是 URI 的官方规范。如果您不喜欢,请向 IETF 提出。
                        • @AlexD 我认为这些可能被视为相对引用。请参阅 RFC 3986,第 4.2 节。
                        • @andyg0808,你可能是对的,但事实仍然是这个正则表达式几乎可以匹配任何字符串。
                        • 根据问题,这不是一个好的答案,因为它没有验证。正在解析。这是两个不同的功能。如果你给这个正则表达式垃圾,它会尝试解析它。如果 URL 无效,则无法保证解析工作。
                        【解决方案21】:

                        我发现的最好的正则表达式是:/(^|\s)((https?:\/\/)?[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?)/gi

                        对于ios swift:(^|\\s)((https?:\\/\\/)?[\\w-]+(\\.[\\w-]+)+\\.?(:\\d+)?(\\/\\S*)?)

                        http://jsfiddle.net/9BYdp/1/

                        找到here

                        【讨论】:

                          【解决方案22】:

                          经过严格的搜索,我最终确定了以下

                          ^[a-zA-Z0-9]+\:\/\/[a-zA-Z0-9]+\.[-a-zA-Z0-9]+\.?[a-zA-Z0-9]+$|^[a-zA-Z0-9]+\.[-a-zA-Z0-9]+\.[a-zA-Z0-9]+$
                          

                          这个东西在未来的 URL 中通用。

                          【讨论】:

                            【解决方案23】:

                            希望对你有帮助……

                            ^(http|https):\/\/+[\www\d]+\.[\w]+(\/[\w\d]+)?
                            

                            【讨论】:

                              【解决方案24】:

                              据我所知,这种表达方式对我来说很好-

                              (https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9]\.[^\s]{2,})
                              

                              工作示例-

                              function RegExForUrlMatch()
                              {
                                var expression = /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9]\.[^\s]{2,})/g;
                              
                                var regex = new RegExp(expression);
                                var t = document.getElementById("url").value;
                              
                                if (t.match(regex)) {
                                  document.getElementById("demo").innerHTML = "Successful match";
                                } else {
                                  document.getElementById("demo").innerHTML = "No match";
                                }
                              }
                              <input type="text" id="url" placeholder="url" onkeyup="RegExForUrlMatch()">
                              
                              <p id="demo">Please enter a URL to test</p>

                              【讨论】:

                                【解决方案25】:

                                这是RegexBuddy 的用途。

                                (\b(https?|ftp|file)://)?[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]
                                

                                它与以下这些匹配(在** ** 标记内):

                                **http://www.regexbuddy.com**  
                                **http://www.regexbuddy.com/**  
                                **http://www.regexbuddy.com/index.html**  
                                **http://www.regexbuddy.com/index.html?source=library**  
                                

                                您可以通过 http://www.regexbuddy.com/download.html 下载 RegexBuddy。

                                【讨论】:

                                • 地鼠呢?可怜的被遗忘的地鼠。
                                • 您的正则表达式与我能想到的任何网址都不匹配 - 包括您提供的网址。我将您的正则表达式粘贴到 rubular.com 中,上面写着“必须转义正斜杠”。是否有错字,或者您可以通过在 rubular.com 上使用它来澄清吗?
                                • @PandaWood 那是因为你需要为 Ruby 格式化。 Ruby 的转义字符是什么?
                                • 作为 JavaScript RegExp 文字:/\b(https?|ftp|file):\/\/[\-A-Za-z0-9+&amp;@#\/%?=~_|!:,.;]*[\-A-Za-z0-9+&amp;@#\/%=~_|]/
                                • 这几乎匹配所有东西......没用
                                【解决方案26】:

                                这个怎么样:

                                ^(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9]\.[^\s]{2,})$
                                

                                这些是测试用例:

                                你可以在here : https://regex101.com/r/mS9gD7/41试试看

                                【讨论】:

                                  【解决方案27】:

                                  这不是正则表达式,但完成相同的事情(仅限 Javascript):

                                  function isAValidUrl(url) {
                                    try {
                                      new URL(url);
                                      return true;
                                    } catch(e) {
                                      return false;
                                    }
                                  }
                                  

                                  【讨论】:

                                  • 这个问题是 h ttp://bla 是一个有效的 URL(h 和 t 之间的空格所以不能使它成为一个实际的 URL)
                                  【解决方案28】:

                                  Getting parts of a URL (Regex) 帖子讨论了解析 URL 以识别其各种组件。如果你想检查一个 URL 是否格式正确,它应该足以满足你的需要。

                                  如果您需要检查它是否真的有效,您最终将不得不尝试访问另一端的任何内容。

                                  不过,一般而言,您最好使用由您的框架或其他库提供给您的函数。许多平台都包含解析 URL 的函数。例如,有 Python 的 urlparse 模块,在 .NET 中,您可以使用 System.Uri class's constructor 作为验证 URL 的方法。

                                  【讨论】:

                                    【解决方案29】:

                                    对我来说最好的 URL 正则表达式是:

                                    "(([\w]+:)?//)?(([\d\w]|%[a-fA-F\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}(:[\d]+)?(/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?"
                                    

                                    【讨论】:

                                    • 这似乎受限于它可以接受的域数量?
                                    • 谢谢!这是在 iOS 上为我工作的转义版本:(([\\w]+:)?//)?(([\\d\\w]|%[a-fA-f\\d]{2,2})+(:([\\d\\w]|%[a-fA-f\\d]{2,2})+)?@)?([\\d\\w][-\\d\\w]{0,253}[\\d\\w]\\.)+[\\w]{2,4}(:[\\d]+)?(/([-+_~.\\d\\w]|%[a-fA-f\\d]{2,2})*)*(\\?(&amp;?([-+_~.\\d\\w]|%[a-fA-f\\d]{2,2})=?)*)?(#([-+_~.\\d\\w]|%[a-fA-f\\d]{2,2})*)?
                                    • 此正则表达式仅匹配最长 4 个字符的后缀,并且在 IP 地址(v4 和 v6)、本地主机和带有外来字符的域名上失败。我建议编辑您的包含大小范围,并至少将 \w 替换为 \p{L}
                                    • 请注意,此 RegEx 不会捕获仅包含一个字母的子域的 URL,例如 "m.sitename.com"。为了解决这个问题,我不得不将([\d\w][-\d\w]{0,253}[\d\w]\.)+ 更改为([\d\w][-\d\w]{0,253}[\d\w]?\.)+(在它的末尾添加一个问号)
                                    • 不适用于something.co.uk
                                    【解决方案30】:

                                    要匹配一个 URL,有多种选择,这取决于您的要求。 以下是少数。

                                    _(^|[\s.:;?\-\]<\(])(https?://[-\w;/?:@&=+$\|\_.!~*\|'()\[\]%#,☺]+[\w/#](\(\))?)(?=$|[\s',\|\(\).:;?\-\[\]>\)])_i
                                    
                                    #\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))#iS
                                    

                                    还有一个链接可以为您提供超过 10 种不同的 URL 验证变体。

                                    https://mathiasbynens.be/demo/url-regex

                                    【讨论】:

                                      猜你喜欢
                                      • 2011-06-10
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2017-02-03
                                      • 2013-11-07
                                      • 2013-06-19
                                      相关资源
                                      最近更新 更多