【问题标题】:Regex to parse long urls正则表达式解析长网址
【发布时间】:2011-08-07 07:22:57
【问题描述】:

我有这个正则表达式,它工作得很好,但不是在所有情况下,例如,如果我有一个长网址说“http://www.gob.cl/especiales/politicas-y-propuestas-de-accion-para- el-desarrollo-de-la-educacion-chilena/”它只会返回“http://www.gob”。作为网址的一部分

这是我的代码

$regexUrl = "((https?|ftp)\:\/\/)?"; // 方案 $regexUrl .= "([a-zA-Z0-9+!*(),;?&=\$_.-]+(\:[a-zA-Z0-9+!*(),;? &=\$_.-]+)?@)?"; // 用户和通行证 $regexUrl .= "([a-zA-Z0-9-]+)\.([a-zA-Z]{2,3})"; //主机或IP $regexUrl .= "(\:[0-9]{2,5})?"; // 港口 $regexUrl .= "(\/([a-zA-Z0-9+\$_-]\.?)+)*\/?"; // 小路 $regexUrl .= "(\?[a-zA-Z+&\$_.-][a-zA-Z0-9;:@&%=+\/\$_.-]*)?"; // 获取查询 $regexUrl .= "(#[a-zA-Z_.-][a-zA-Z0-9+\$_.-]*)?"; // 锚 //if(preg_match_all("#\bhttps?://[^\s()]+(?:\([\w\d]+\)|([^[:punct:]\s]|/ ))#", $message, $matches1, PREG_PATTERN_ORDER)) //$pattern = '/((https?|ftp)\:(\/\/)|(文件\:\/{2,3}))?(((25[0-5]|2[0 -4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9] |[01]?[0-9][0-9]?))|(((([a-zA-Z0-9]+)(\.)?)+)(\.)(com|org |net|gov|mil|biz|info|mobi|name|aero|jobs|museum|[a-z]{2}))([\/][\/a-zA-Z0-9\.]*)* ([\/]?(([\?][a-zA-Z0-9]+[\=][a-zA-Z0-9\%\(\)]*)([\&][a -zA-Z0-9]+[\=][a-zA-Z0-9\%\(\)]*)*))?/'; if(preg_match_all("/$regexUrl/", $urlMessage, $matches1, PREG_PATTERN_ORDER)) { 尝试 { foreach($matches1[0] as $urlToTrim1) { $url= $urlToTrim1; 回声 $url; } } 捕获(异常 $e) { $url="-1"; } }

是否有一个通用的正则表达式可以解析所有类型的网址。

【问题讨论】:

    标签: php regex url


    【解决方案1】:

    您的主机或 ip 正则表达式部分

    "([a-zA-Z0-9-]+)\.([a-zA-Z]{2,3})"
    

    最多允许一个点在里面。因此“www.xyz.com”永远无法匹配。

    我不知道你的具体要求是什么,但你可以选择类似的东西

    "([^/?#:]+)"
    

    主机部分。

    【讨论】:

      【解决方案2】:

      这是我从 $text 中提取所有 URL 的方法:

      preg_match_all('#(https?://[a-z0-9\.\-_\#%&=/?;,!:~@\$\+]+)#iu', $text, $m);
      

      假设 URL 以 https:// 或 http:// 开头,然后可以有一个限制为一组特殊字符的序列。

      然后我可以在$m 上使用http://www.php.net/manual/en/function.parse-url.php 来获取所有URL 的详细信息

      编辑:另外,如果您正在解析文本,您可能需要检查 URL 末尾的句点 (.) 和其他标点符号。我注意到如果 URL 位于句子的末尾,例如 http://example.com,人类可能会在 URL 的末尾添加 .

      所以我做了这样的事情:

       if (($url[$pos]==='!') || ($url[$pos]==='.')) { // probably do not want these chars at the end of a url!
          $url = substr($url, 0, $pos);
       }
      

      【讨论】:

      • +1。如果最后一个匹配的字符是被禁止的字符之一,您还可以使用后向强制正则表达式本身退出:'#https?://[a-z0-9._\#%&=/?;,!:~@$+-]+(?<![.!])#iu'
      【解决方案3】:

      如何匹配所有以 http:// 或 https:// 开头的内容

      ((?:http|https)(?::\\/{2}[\\w]+)(?:[\\/|\\.]?)(?:[^\\s"]*))

      【讨论】:

      • (1) (?:http|https) 不必要地冗长且效率低下; https? 工作得很好。 (2)/只有在使用/作为正则分隔符时才需要转义;还有许多其他选择。 (3) 如果您使用' 而不是" 作为字符串文字分隔符,则不需要双重转义。 (4) 在字符类中,. 不需要转义,| 不是“OR”运算符,它只匹配 |(隐含“OR”)。 (5) [/.]? 无论如何都是毫无意义的,因为 [^\s"]* 匹配这两个字符。 (6) 无需将整个正则表达式包装在() 中。 (...) 我可以继续... ;)
      • 嗯,它正确匹配了 OP 提供的一个示例。如果 URL 总是用双引号括起来,就像它们在问题的文本中一样,你没关系,但我认为这不是 OP 的意思。 (但无论如何我错了:你的正则表达式也匹配"http://www.gob." 中的http://www.gob.,这显然是不正确的。)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多