【问题标题】:Can a URL contain a semicolon and still be valid?URL 可以包含分号并且仍然有效吗?
【发布时间】:2010-11-13 18:18:50
【问题描述】:

我正在使用正则表达式将纯文本 URL 转换为可点击的链接。

@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.-]*(\?\S+)?)?)?)@

但是,有时在文本正文中,URL 每行枚举一个,末尾有一个分号。真实网址不包含任何“;”。

http://www.aaa.org/pressdetail.asp?PRESS_REL_ID=275;
http://www.aaa.org/pressdetail.asp?PRESS_REL_ID=123;
http://www.aaa.org/pressdetail.asp?PRESS_REL_ID=124

是否允许在 URL 中使用分号 (;) 或者分号是否可以视为 URL 结尾的标记?这如何适合我的正则表达式?

【问题讨论】:

    标签: regex url syntax uri


    【解决方案1】:

    一个semicolon is reserved 并且只能用于其特殊目的(取决于方案)。

    第 2.2 节:

    许多 URL 方案保留某些 具有特殊含义的字符: 他们出现在 URL 中特定于方案的部分有一个 指定的语义。如果性格 对应于一个八位字节是 在方案中保留,八位字节必须 被编码。那些角色 ”;”, “/”、“?”、“:”、“@”、“=”和“&”是 可能的字符 为特定含义而保留 方案。不能有其他字符 在一个方案中保留。

    【讨论】:

    • 我迟到了,但这段代码明确处理 http/https url,它允许 ;作为查询字符串分隔符(而不是 &)...实际上,Ben 已经涵盖了这一点。
    【解决方案2】:

    W3C 鼓励 CGI 程序接受;以及查询字符串中的 & (即以相同方式处理 ?name=fred&age=50?name=fred;age=50)。这应该是因为 & 必须被编码为 &在 HTML 中,而 ;没有。

    【讨论】:

    【解决方案3】:

    分号是合法的URI字符;它属于子分隔符类别:http://www.ietf.org/rfc/rfc3986.txt

    然而,规范声明半色对于 特定 URI 是否合法取决于该 URI 的方案或生产者。因此,如果使用这些链接的网站不允许使用分号,那么它们在特定情况下无效。

    【讨论】:

      【解决方案4】:

      从技术上讲,分号是 URL 字符串中的合法子分隔符;上面引用了大量源材料,包括http://www.ietf.org/rfc/rfc3986.txt

      有些人确实将它用于合法目的,尽管它的使用可能是特定于站点的(即,仅用于该站点),因为它的用途必须由使用它的站点来定义。

      然而,在现实世界中,URL 中分号的主要用途是将病毒或网络钓鱼 URL 隐藏在合法 URL 后面。

      例如,向某人发送带有此链接的电子邮件:

      http://www.yahoo.com/junk/nonsense;0200.0xfe.0x37.0xbf/malicious_file/

      将导致 Yahoo!链接(www.yahoo.com/junk/nonsense)被忽略,因为即使它是合法的(即格式正确),也不存在这样的页面。但是第二个链接(0200.0xfe.0x37.0xbf/malicious_file/)可能存在*,用户将被引导到恶意文件页面;然后,一个公司的 IT 经理会收到一份报告,而且很可能会收到一张粉单。

      在所有反对者发脾气之前,这正是新的 Facebook 网络钓鱼问题的工作原理。为了像往常一样保护有罪的人,名字已经改变了。

      *据我所知,实际上不存在这样的页面。显示的链接仅用于本次讨论。

      【讨论】:

      • 哪个应用程序会打开0200.0xfe.0x37.0xbf,因为它知道雅虎链接会返回 404 状态?!对我来说没有意义。
      【解决方案5】:

      http://www.ietf.org/rfc/rfc3986.txt 涵盖 URL 以及哪些字符可能以未编码的形式出现。鉴于包含分号的 URL 在浏览器中正常工作,您的代码应该支持它们。

      【讨论】:

        【解决方案6】:

        是的,分号在 URL 中有效。但是,如果您从相对非结构化的散文中提取它们,则可以安全地假设 URL 的 end 处的分号表示句子标点符号。句号、问号、引号等其他句子标点符号也是如此。

        如果您只对具有显式 http[s] 协议的 URL 感兴趣,并且您的正则表达式支持后向搜索,那么这个正则表达式就足够了:

        https?://[\w!#$%&'()*+,./:;=?@\[\]-]+(?<![!,.?;:"'()-])

        在协议之后,它只是匹配一个或多个在 URL 中可能有效的字符,根本不用担心结构。但随后它会根据需要退回尽可能多的位置,直到最后一个字符不是句子标点符号。

        【讨论】:

          【解决方案7】:

          引用 RFC 对回答这个问题并没有太大帮助,因为您会遇到带有分号(以及与此相关的逗号)的 URL。我们有一个不处理分号和逗号的正则表达式,我们在 NutshellMail 的一些用户抱怨说,因为包含它们的 URL 实际上存在于野外。尝试在 Facebook 或 Twitter 中构建一个包含“;”的虚拟 URL或“,”,您会看到这两个服务正确地编码了完整的 URL。

          我用以下模式替换了我们正在使用的正则表达式(并测试了它是否有效):

           string regex = @"((www\.|(http|https|ftp|news|file)+\:\/\/)[&#95;.a-zA-Z0-9-]+\.[a-zA-Z0-9\/&#95;:@=.+?,##%&~_-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)])";
          

          这个正则表达式来自http://rickyrosario.com/blog/converting-a-url-into-a-link-in-csharp-using-regular-expressions/(稍作修改)

          【讨论】:

          • 我添加了代码格式以便我们可以更轻松地阅读它,但我不建议使用该正则表达式。撇开明显的网络修改和许多多余的反斜杠和管道不谈,最后两个字符类存在严重缺陷。它们不仅排除分号和括号等有效字符,最后一个匹配各种无效字符,如引号、大括号和非ASCII字符。
          猜你喜欢
          • 1970-01-01
          • 2017-05-13
          • 2020-04-10
          • 2014-08-03
          • 1970-01-01
          • 2011-10-16
          • 2018-06-04
          • 2018-04-08
          • 2012-05-23
          相关资源
          最近更新 更多