【问题标题】:Regex to replace relative link with root relative link正则表达式用根相对链接替换相对链接
【发布时间】:2011-02-21 15:03:32
【问题描述】:

我有一个文本字符串,其中包含带有所有不同类型链接(相对、绝对、根相对)的 html。我需要一个可以由 PHP 的 preg_replace 执行的正则表达式,以用根相对链接替换所有相对链接,而无需触及任何其他链接。我已经有了根路径。

替换链接:

<tag ... href="path/to_file.ext" ... >   --->   <tag ... href="/basepath/path/to_file.ext" ... >
<tag ... href="path/to_file.ext" ... />   --->   <tag ... href="/basepath/path/to_file.ext" ... />

未改动的链接:

<tag ... href="/any/path" ... >
<tag ... href="/any/path" ... />
<tag ... href="protocol://domain.com/any/path" ... >
<tag ... href="protocol://domain.com/any/path" ... />

【问题讨论】:

  • 必须是正则表达式吗?使用 DOM 类可以得到更准确的结果。
  • 它必须是正则表达式,因为我无法保证 DOM 足够有效,任何基本的 DOM 阅读器都能正确解析。

标签: php regex hyperlink relative-path absolute-path


【解决方案1】:

我想出了这个:

preg_replace('#href=["\']([^/][^\':"]*)["\']#', $root_path.'$1', $html);

这可能有点过于简单了。我看到的一个明显缺陷是,当它在标签之外时,它也会匹配href="something",但希望它可以让你开始。

【讨论】:

    【解决方案2】:

    如果你只是想改变基础 URI,你可以试试BASE element

    <base href="/basepath/">
    

    但请注意,更改基本 URI 会影响所有相对 URI,而不仅仅是相对 URI 路径。

    否则,如果您真的想使用正则表达式,请考虑您想要的相对路径必须是 path-noscheme 类型(请参阅RFC 3986):

    path-noscheme = segment-nz-nc *( "/" segment )
    segment       = *pchar
    segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
                    ; non-zero-length segment without any colon ":"
    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
    pct-encoded   = "%" HEXDIG HEXDIG
    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
                  / "*" / "+" / "," / ";" / "="
    

    所以 URI 的开头必须匹配:

    ^([a-zA-Z0-9-._~!$&'()*+,;=@]|%[0-9a-fA-F]{2})+($|/)
    

    但是请使用适当的 HTML 解析器来解析 HTML 并以此构建 DOM。然后就可以查询DOM获取href属性,用上面的正则表达式测试值。

    【讨论】:

    • 基本标签工作得几乎完美,只是它似乎与 href="#test" 之类的链接混淆了,它将它们变成了 href="/basepath/#test"。从好的方面来说,href="link#test" 变成了 href="/basepath/link#test",这是可行的。有没有办法让锚在不知道任何当前 url 的情况下与基类一起工作?
    • 以上评论其实是webkit(safari, chrome)和IE中的一个bug,在Firefox中可以正常使用。
    • @Kendall Hopkins:正如我所说:所有相对 URI 都会受到影响。 #test 是一个相对 URI。我宁愿说这是 Firefox 中的一个错误,它不能将 #test 的基本 URI 解析为 /basepath//basepath/#test。 (我认为 Firefox 使用 RFC 2396 的算法,而其他使用 RFC 3986 的算法,该算法在五年前已经过时 RFC 3986。)
    猜你喜欢
    • 2014-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    相关资源
    最近更新 更多