网址分裂在PHP中

时间:2009-07-09 07:59:45

标签: php

我有一个这样的网址:

  

http://www.w3schools.com/PHP/func_string_str_split.asp

我想将该网址拆分为仅获取主机部分。为此,我正在使用

parse_url($url,PHP_URL_HOST);

它返回www.w3schools.com。 我想只获得'w3schools.com'。 是否有任何功能或我必须手动完成?

3 个答案:

答案 0 :(得分:6)

有很多方法可以做到这一点。如果您知道总是想要剥离“www。”

,那么简单的替换是最快的
$stripped=str_replace('www.', '', $domain);

正则表达式替换允许您将该匹配绑定到字符串的开头:

$stripped=preg_replace('/^www\./', '', $domain);

如果它始终是域的第一部分,无论其是否为www,您都可以使用explode / implode。虽然它很容易阅读,但它是效率最低的方法:

$parts=explode('.', $domain);
array_shift($parts); //eat first element
$stripped=implode('.', $parts);

正则表达式可以更有效地实现相同的目标:

$stripped=preg_replace('/^\w+\./', '', $domain);

现在您可能会想到以下内容比上述正则表达式更有效:

$period=strpos($domain, '.');
if ($period!==false)
{
    $stripped=substr($domain,$period+1);
}
else
{
    $stripped=$domain; //there was no period
}

但我对它进行了基准测试,发现超过一百万次迭代,preg_replace版本始终如一地击败它。典型结果,归一化为最快(因此它的无单位时间为1):

  • 简单的str_replace:1
  • preg_replace with /^\w+\./:1.494
  • strpos / substr:1.982
  • 爆炸/内爆:2.472

以上代码示例总是剥离第一个域组件,因此可以在“www.example.com”和“www.example.co.uk”等域上正常工作,但不能“example.com”或“www。 department.example.com”。如果您需要处理可能已经是主域的域,或者有多个子域(例如“foo.bar.baz.example.com”)并希望将它们简化为主域(“example.com”) ,尝试以下。每种方法中的第一个样本仅返回最后两个域组件,因此不适用于“co.uk”类域。

  • explode

    $parts = explode('.', $domain);
    $parts = array_slice($parts, -2);
    $stripped = implode('.', $parts);
    

    由于explode始终是最慢的方法,因此编写处理“co.uk”的版本没什么意义。

  • 正则表达式:

    $stripped=preg_replace('/^.*?([^.]+\.[^.]*)$/', '$1', $domain);
    

    这将捕获域中的最后两个部分,并用捕获的部分替换完整的字符串值。对于多个子域,所有主要部分都将被剥离。

    要使用“.co.uk”类似的域以及可变数量的子域,请尝试:

    $stripped=preg_replace('/^.*?([^.]+\.(?:[^.]*|[^.]{2}\.[^.]{2}))$/', '$1', $domain);
    
  • STR:

    $end = strrpos($domain, '.') - strlen($domain) - 1;
    $period = strrpos($domain, '.', $end);
    if ($period !== false) {
        $stripped = substr($domain,$period+1);
    } else {
        $stripped = $domain;
    }
    

    允许co.uk域名:

    $len = strlen($domain);
    if ($len < 7) {
        $stripped = $domain;
    } else {
        if ($domain[$len-3] === '.' && $domain[$len-6] === '.') {
            $offset = -7;
        } else {
            $offset = -5;
        }
        $period = strrpos($domain, '.', $offset);
        if ($period !== FALSE) {
            $stripped = substr($domain,$period+1);
        } else {
            $stripped = $domain;
        }
    }
    

通过牺牲边缘情况(主域组件是单个字母,例如“a.com”),可以使得基于正则表达式和str的实现速度更快一些:

  • 正则表达式:

    $stripped=preg_replace('/^.*?([^.]{3,}\.(?:[^.]+|[^.]{2}\.[^.]{2}))$/', '$1', $domain);
    
  • STR:

    $period = strrpos($domain, '.', -7);
    if ($period !== FALSE) {
        $stripped = substr($domain,$period+1);
    } else {
        $stripped = $domain;
    }
    

虽然行为发生了变化,但排名并非(大部分时间)。他们在这里,时间标准化为最快。

  • 多子域正则表达式:1
  • .co.uk正则表达式(快速):1.01
  • .co.uk str(fast):1.056
  • .co.uk正则表达式(正确):1.1
  • .co.uk str(correct):1.127
  • 多子域名str:1.282
  • 多个子域爆炸:1.305

在这里,时间之间的差异非常小,以至于并不罕见。例如,快速.co.uk正则表达式经常击败基本的多子域正则表达式。因此,确切的实施不应对速度产生明显影响。相反,选择一个基于简单性和清晰度。只要您不需要处理.co.uk域,那就是多子域正则表达式方法。

答案 1 :(得分:0)

您必须自己剥离子域部分 - 没有内置函数。

// $domain beeing www.w3scools.com
$domain = implode('.', array_slice(explode('.', $domain), -2));

以上示例也适用于无限深度的子域,因为它将返回最后两个域部分(域和顶级域)。

如果您只想剥离 www。,您只需执行str_replace(),这样会更快:

$domain = str_replace('www.', '', $domain);

答案 2 :(得分:0)

当且仅当返回的字符串中出现[。]超过1次时,您需要在[。]字符的第一个出现之前删除任何字符(以及[。]本身)。

例如,如果返回的字符串是www-139.in.ibm.com,则正则表达式应该返回in.ibm.com,因为那将是域。

如果返回的字符串是music.domain.com,则正则表达式应返回domain.com

在极少数情况下,您可以访问没有服务器前缀的站点,您可以使用http://domain.com/pageurl访问该站点,在这种情况下,您可以直接将域名作为domain.com获取,在这种情况下,正则表达式不应剥离任何东西

IMO这应该是正则表达式的伪逻辑,如果你想我可以为你形成一个包含这些东西的正则表达式。