【问题标题】:Regex for Replacing Absolute URLs with Relative URLs用相对 URL 替换绝对 URL 的正则表达式
【发布时间】:2019-07-16 00:32:33
【问题描述】:

如何编写将任何绝对 URL 转换为相对路径的正则表达式。例如:

src="http://www.test.localhost/sites/ 

会变成

src="/sites/"

域不是静态的。

我不能使用 parse_url(根据 answer),因为它是更大字符串的一部分,其中也包含无 url 数据。

【问题讨论】:

  • 用空字符串替换https?:\/\/[\w.-]+(?=\/)
  • 您的问题不清楚,因为您说您的数据是“较大字符串的一部分”,但我们不知道那是什么。如果它是有效的 html,那么您应该只阅读 Casimir 的答案。如果它不是有效的 html,那么您可能需要涵盖一系列晦涩难懂的案例——那是什么?

标签: php regex preg-replace


【解决方案1】:

解决方案

您可以使用以下正则表达式:

/https?:\/{2}[^\/]+/

这将匹配以下内容:

http://www.test.localhost/sites/
http://www.domain.localhost/sites/
http://domain.localhost/sites/

原来是这样:

$domain = preg_replace('/https?:\/{2}[^\/]+/', '', $domain);

说明

http: Look for 'http'
s?: Look for an 's' after the 'http' if there's one
: : Look for the ':' character
\/{2}: Look for the '//'
[^\/]+: Go for anything that is not a slash (/)

【讨论】:

  • 这是否适用于更大的字符串,例如

    click test.localhost/sites/">here</a></p> 将返回:

    click 这里

  • @Sam 如果这是一个 HTML 字符串,我不建议使用正则表达式。使用 HTML parser 提取 URL,然后使用您在解析 URL 部分时提到的答案中的方法。
【解决方案2】:

我的猜测是,也许这个表达式或它的改进版本可能会在某种程度上起作用:

^\s*src=["']\s*https?:\/\/(?:[^\/]+)([^"']+?)\s*["']$

表达式在this demo 的右上方面板中进行了解释,如果您想探索/简化/修改它。


测试

$re = '/^\s*src=["\']\s*https?:\/\/(?:[^\/]+)([^"\']+?)\s*["\']$/m';
$str = 'src=" http://www.test.localhost/sites/  "
src=" https://www.test.localhost/sites/"
src=" http://test.localhost/sites/   "
  src="https://test.localhost/sites/   "
      src="https://localhost/sites/   "
src=\'https://localhost/   \'
src=\'http://www.test1.test2.test3.test4localhost/sites1/sites2/sites3/   \'';
$subst = 'src="$1"';

var_export(preg_replace($re, $subst, $str));

输出

src="/sites/"
src="/sites/"
src="/sites/"
src="/sites/"
src="/sites/"
src="/"
src="/sites1/sites2/sites3/"

正则表达式电路

jex.im 可视化正则表达式:

【讨论】:

  • 你怎么知道OP的实际输入在行首有src? ...诡计问题,你不知道 - 因为问题是不清楚的。
【解决方案3】:
$dom = new DOMDocument;
$dom->loadHTML($yourHTML)
$xp = new DOMXPath($dom);

foreach($xp->query('//@src') as $attr) {
    $url = parse_url($attr->nodeValue);

    if ( !isset($url['scheme']) || stripos($url['scheme'], 'http']) !== 0 )
        continue;

    $src = $url['path']
         . ( isset($url['query']) ? '?' . $url['query'] : '' )
         . ( isset($url['fragment']) ? '#' . $url['fragment'] : '' );

    $attr->parentNode->setAttribute('src', $src);
}

$result = $dom->saveHTML();

我添加了一个if 条件来跳过无法判断 src 属性的开头是域还是路径的开头的情况。根据您要执行的操作,您可以删除此测试。

如果您使用的是 html 文档的一部分(即:不是完整的文档),您必须将 $result = $dom-&gt;saveHTML() 更改为:

$result = '';
foreach ($dom->getElementsByTagName('body')->item(0)->childNodes as $childNode) {
    $result . = $dom->saveHTML($childNode);
}  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    • 2018-12-13
    • 1970-01-01
    相关资源
    最近更新 更多