【问题标题】:How to filter URLs that contain white space with preg match?如何使用 preg 匹配过滤包含空格的 URL?
【发布时间】:2014-02-04 10:54:57
【问题描述】:

我解析包含多个链接的文本。其中一些包含空格,但有一个文件结尾。我目前的模式是:

preg_match_all('#\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))#', $links, $match);

同样的方法:

preg_match_all('/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/', $links, $match);

我对这些模式了解不多,也没有找到一个很好的教程来解释所有可能的模式的含义并显示示例。

如何过滤这样的 URL: http://my-url.com/my doc.doc 甚至是http://my-url.com/my doc with more white spaces.doc

preg_match_all 函数中的\s 代表一个空格。但是如何检查是否有一个文件以一个或一些空格结尾?

有可能吗?

【问题讨论】:

  • 您无法过滤此类网址。如果我写Go to http://www.google.com/search and type your search query。您如何以编程方式知道该 url 是 http://www.google.com/searchhttp://www.google.com/search and type?也许有一些自然语言分析,但即使这样也不是很明显。
  • urlencode 可能就是你要找的东西
  • 啊好吧!这很可悲,因为这些 URL 存在。我以为我可以过滤它们。不过没关系,我只需要重命名文件。

标签: php regex url preg-match whitespace


【解决方案1】:

为什么不直接使用 PHP 的 FILTER 函数。 ?

<?php
$url = "http://my-url.com/my doc.doc";

if(!filter_var($url, FILTER_VALIDATE_URL))
{
    echo "URL is not valid";
}
else
{
    echo "URL is valid";
}

OUTPUT :

URL is not valid

【讨论】:

  • 不,这根本没有帮助,因为我以前不知道这些 URL。我通过文本解析找到它们。即使 URL 或者假设文件名是愚蠢的,它们也不是无效的并且它们在浏览器中工作,但似乎无法过滤它们:(
【解决方案2】:

这可能是您正在寻找的使用urlencode的内容

$file = "my doc with more white spaces.doc";
echo " http://my-url.com/" . urlencode($file);

产生:

http://my-url.com/my+doc+with+more+white+spaces.doc

rawurlencode

产生:

http://my-url.com/my%20doc%20with%20more%20white%20spaces.doc

编辑:以下内容可能有助于使用parse_url解析您的网址

DEMO

$url = 'http://my-url.com/my doc with more white spaces.doc';
$purl = parse_url($url);
$rurl = "";
if(isset($purl['scheme'])){
    $rurl .= $purl['scheme'] . "://";
}
if(isset($purl['host'], $purl['path'])){
    $rurl .= $purl['host'] . rawurlencode($purl['path']);
}
if($rurl === ""){
    $rurl = $url;#error parsing error/invalid url?
}

对于你可以做的子目录

$purl['path'] = implode('/', array_map(function($value){return rawurlencode($value);}, explode('/', $purl['path'])));

【讨论】:

  • 谢谢!如果我以前知道 URL,那会起作用,但是我通过文本解析获得 URL,所以这对我不起作用。:(
  • 谢谢!但实际上我什至没有尝试过,因为我的代码已经完成了这项工作;)但是您的代码也适用于子目录吗?例如:www.my-url.com/subfolder/another_subfolder/my file.doc
  • @user2718671 是的,但它也编码/,所以你需要爆炸->编码->然后用/内爆
【解决方案3】:

我对php不太了解,但是这个正则表达式

(http|ftp)(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?

即使有空格也会匹配每个网址

我认为这个正则表达式可以。

【讨论】:

  • 它似乎有问题,因为我收到以下错误:“未知修饰符 '('”。但是 preg_match_all('#\bhttps?://[^()"]+# ', $links, $match); 已经完成了这项工作,因为所有链接都在引号内。无论如何谢谢!:)
【解决方案4】:

使用这个正则表达式

preg_match_all("/^(?si)(?>\s*)(((?>https?:\/\/(?>www\.)?)?(?=[\.-a-z0-9]{2,253}(?>$|\/|\?|\s))[a-z0-9][a-z0-9-]{1,62}(?>\.[a-z0-9][a-z0-9-]{1,62})+)(?>(?>\/|\?).*)?)?(?>\s*)$/", $input_lines, $output_array);

Demo

【讨论】:

  • 谢谢。但不幸的是,它对我不起作用。我正在解析整个文本,而您的正则表达式只返回一个空数组:(
【解决方案5】:

做了this really helpful tutorial 之后,我终于知道正则表达式的语法是如何工作的了。完成后我在this site进行了一些实验

发现我的已解析文档中的所有超链接都在引号之间之后,这很容易,所以我只需将正则表达式更改为:

preg_match_all('#\bhttps?://[^()<>"]+#', $links, $match);

因此在" 之后,它正在寻找以http 开头的下一个匹配项。

但这还不是完整的解决方案。用户类是正确的 - 没有 rawurlencode 文件名将无法工作。

所以下一步是这样的:

function endsWith($haystack, $needle)
{
    return $needle === "" || substr($haystack, -strlen($needle)) === $needle;
}

if(endsWith($textlink, ".doc") || endsWith($textlink, ".docx") || endsWith($textlink, ".pdf") || endsWith($textlink, ".jpg") || endsWith($textlink, ".jpeg") || endsWith($textlink, ".png")){
        $file = substr( $textlink, strrpos( $textlink, '/' )+1 );
        $rest_url=substr($textlink, 0, strrpos($textlink, '/' )+1 );
        $textlink=$rest_url.rawurlencode($file);            
    }

从 URL 中过滤文件名并对它们进行原始编码,以便输出链接正确。

【讨论】:

  • debuggex 也是一个很好的带有视觉辅助的正则表达式调试器
【解决方案6】:

我认为这应该可行:

$url = '...';
$url_new = '';
$array = explode(' ',$url);

foreach($array as $name => $val){
    if ($val!=' '){
         $url_new = $url_new.$val;
    }
}

【讨论】:

  • 问题是我以前不知道网址。我使用上面的 preg_match_all 函数解析文本以获取它们。我认为可以使用另一个正则表达式来过滤它们,该正则表达式检查空格后是否有文件结尾(doc | docx | pdf)或其他东西......
  • 您将结果存储在哪里?
  • 在一个数组中 - 每个条目都是一个带有链接的字符串
  • 好吧好吧。因此,在您使用我发布的代码检查所有文本后,为该数组添加 foreach。
  • preg_match_all('#\bhttps?://[^\s()]+(?:([\w\d]+)|([^[:punct:]\ s]|/))#', $links, $match);是用于解析文本的过滤器,所以我得到的只是不完整的 URL。这就是为什么您的函数无济于事的原因,因为问题出在正则表达式;)
猜你喜欢
  • 2020-04-06
  • 2015-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多