【问题标题】:How do I write a regular expression for a URL without the scheme?如何在没有方案的情况下为 URL 编写正则表达式?
【发布时间】:2009-06-09 16:06:04
【问题描述】:

如何编写一个 RE 来验证没有该方案的 URL:

通过:

  • www.example.com
  • example.com

失败:

【问题讨论】:

  • 您能具体说明 URL 的含义吗?只是 HTTP URL?你想在那里允许什么?只是您的示例中显示的主机部分?
  • command.com 和 win.com 呢?找出一个带有单个句点的单词是一个 URL 是自找麻烦。
  • @jmucchiello:我不认为他需要一个可以从某些文本中提取 URL 的正则表达式。我宁愿怀疑它是用于输入验证。
  • 我正在尝试验证没有资源类型的 url,如排除“HTTP://”部分。愚蠢的做法是如果 url.starts_with("HTTP://") 失败。我不想提取任何东西,只是一个简单的验证。

标签: regex url


【解决方案1】:
^[A-Za-z0-9][A-Za-z0-9.-]+(:\d+)?(/.*)?$
  • 字符串必须以 ASCII 字母或数字开头
  • ASCII 字母、数字、点和破折号(不允许使用斜线或冒号)
  • 可选:允许端口 (":8080")
  • 可选:斜线后面的任何内容都可以跟在后面(因为您说的是“URL”)
  • 然后是字符串的结尾

想法:

  • 不允许换行
  • 没有有效性或完整性检查
  • 不支持“国际化域名”(IDN)
  • 如果您愿意,可以省略“可选:”部分,但请务必包含最后的“$

如果您的正则表达式支持它,您可以将以上内容缩短为:

^[A-Za-z\d][\w.-]+(:\d+)?(/.*)?$

请注意,\w可能在某些正则表达式中包含 Unicode 字符。此外,\w 包含下划线,在主机名中无效。像第一个这样的显式方法会更安全。

【讨论】:

  • 实际上 RFC 有一个 domainlabel 作为可能的第一个标记,定义为 alphanum。 [ 域标签 = 字母数字 |字母数字 *( 字母数字 | "-" ) 字母数字 ]。所以看起来你的第一个要点是错误的。
  • 对我来说读作“(alphanum)或(alphanum plus(任意数量的alphanum或'-')加上alphanum)”。我在这里错过了什么?
  • 您的正则表达式以 alpha 开头,不包括第一个位置的合法数字。这就是 Axeman 所说的。
  • 哦,我明白了。我的不好,我要注意连字符。 :-) 已更正,谢谢指出。
【解决方案2】:

如果您尝试对一些真实代码执行此操作,请找到适用于您的语言的 URL 解析库并使用它。如果您不想使用它,请查看它的作用。

您称之为“资源”的东西称为“方案”。它记录在RFC 1738 中,上面写着:

[2.1] ... 一般情况下,URL 的写法如下:

   <scheme>:<scheme-specific-part>

URL 包含正在使用的方案的名称 () 由一个冒号,然后是一个字符串(),其 解释取决于方案。

而且,后来在 BNF 中,

方案 = 1*[ 低阿尔法 |数字 | "+" | "-" | “。” ]

所以,如果有一个方案,你可以匹配它:

/^[a-z0-9+.-]+:/i

如果匹配,则您拥有 URL 语法认为的方案,并且您的验证失败。如果你有带有端口号的字符串,比如 www.example.com:80,那么事情就会变得一团糟。在实践中,我还没有处理 -. 的方案,所以你可能会添加一个现实世界的软糖来解决这个问题,直到你决定使用一个合适的库。

除此之外的任何事情,例如检查现有和可访问的域等,最好留给已经弄清楚的库。

【讨论】:

    【解决方案3】:

    URL 语法是quite complex,你需要把它缩小一点。如果足够的话,你可以匹配anything.ext:

    ^[a-zA-Z0-9.]+\.[a-zA-Z]{2,4}$
    

    【讨论】:

    • 这不适用于包含多个点的示例输入。
    【解决方案4】:

    我的猜测是

    /^[\p{Alnum}-]+(\.[\p{Alnum}-]+)+$/
    

    在更原始的 RE 语法中

    /^[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)+$/
    

    甚至更原始:

    /^[0-9A-Za-z-][0-9A-Za-z-]*\.[0-9A-Za-z-][0-9A-Za-z-]*(\.[0-9A-Za-z-][0-9A-Za-z-]*)*$/
    

    【讨论】:

      【解决方案5】:

      谢谢大家,我想我有一个 Python 和一个 PHP 解决方案。他们在这里:

      Python 解决方案:

      import re
      
      url = 'http://www.foo.com'
      p = re.compile(r'^(?!http(s)?://$)[A-Za-z][A-Za-z0-9.-]+(:\d+)?(/.*)?$')
      m = p.search(url)
      print m     # m returns _sre.SRE_Match if url is valid, otherwise None 
      

      PHP 解决方案:

      $url = 'http://www.foo.com';
      preg_match('/^(?!http(s)?:\/\/$)[A-Za-z][A-Za-z0-9\.\-]+(:\d+)?(\/\.*)?$/', $url);
      

      【讨论】:

      • url还是无效的,但如果你坚持,我还是可以处理的。
      猜你喜欢
      • 1970-01-01
      • 2022-11-14
      • 1970-01-01
      • 2020-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多