如何在preg替换中忽略尾部斜线


how to ignore the trailing slash in a preg replace

假设我有两个不同版本的链接发布在我的网站上。。。

  • https://vine.co/v/iF20jKHvnqg
  • https://vine.co/v/iF20jKHvnqg/

(差异为尾随/)

一旦帖子在我的网站上提交,它们就会变成超链接,看起来如下:

<a href="https://vine.co/v/iF20jKHvnqg" target="_blank">https://vine.co/v/iF20jKHvnqg</a>

我已经设置了一个preg替换来捕获vine链接并将其转换为嵌入(这条帖子消息显然包含更多内容,但这是为了示例:

$this->post['message'] = '<a href="https://vine.co/v/iF20jKHvnqg" target="_blank">https://vine.co/v/iF20jKHvnqg</a>';
$drc_embed_vine =  '<iframe src="https://vine.co/v/'2/embed/simple" width="480" height="480" frameborder="0"></iframe>';
$this->post['message'] = preg_replace('~(<a href="https?://vine.co)/v/(.*)" target="_blank">(https?://vine.co)/v/(.*)<'/a>~', $drc_embed_vine, $this->post['message']);

我使用通配符(.*),我认为它的意思是"任何东西",但出于某种原因,如果链接是用尾部斜杠发布的,它不会被转换。。。

我尝试过将我的reg ex更改为(只是我尝试过的几个例子)

~(<a href="https?://vine.co)/v/(.*)/" target="_blank">(https?://vine.co)/v/(.*)/<'/a>~

然后转换带有尾部反斜杠的链接并忽略不带的链接。

~(<a href="https?://vine.co)/v/(.*)/?" target="_blank">(https?://vine.co)/v/(.*)/?<'/a>~

我只是觉得也许是?我使用https检查也会做同样的事情,但什么都没做。

然后说嘿,等等,那不在reg ex中,所以我像一样尝试了一下

~(<a href="https?://vine.co)/v/(.*/?)" target="_blank">(https?://vine.co)/v/(.*/?)<'/a>~

但仍然没有运气。

如何使我的替换不在乎是否有尾随反斜杠?

如果您只需要这个非常特定的替换,您可以直接连接字符串。

$message = rtrim($post['message'], '/');
$message = sprintf('<iframe src="%s/embed/simple" width="480" height="480" frameborder="0"></iframe>', $message);

或者,如果您真的想使用preg_replace:

$pattern = '~https?://vine.co/v/([^/]+)~';
$this->post['message'] = preg_replace($pattern, $drc_embed_vine, $this->post['message']);

您的模式需要与输入字符串($this->post['message'])相匹配。然后,将匹配结果($1)放入最终字符串中。

为了不在乎后面的斜杠,只需考虑视频ID永远不会包含斜杠:显然,它是字母数字[a-zA-Z0-9]。我们采用除带有([^/]+)的尾部斜杠之外的所有字符。您可以将([a-z0-9])i修饰符一起使用。

您在最后一个字符串上构建了一个模式,并试图将其与输入字符串匹配。

此脚本:

<?php
$message = 'https://vine.co/v/iF20jKHvnqg/';
$drc_embed_vine = '<iframe src="https://vine.co/v/'1/embed/simple" width="480" height="480" frameborder="0"></iframe>';
$pattern = '~https?://vine.co/v/([^/]+)/?~';
echo preg_replace($pattern, $drc_embed_vine, $message);

产生这个:

<iframe src="https://vine.co/v/iF20jKHvnqg/embed/simple" width="480" height="480" frameborder="0"></iframe>

编辑

根据您的评论,这里有一个新的模式,以匹配提交的URL上的链接:

$pattern = '~^(<[^>]+>)https?://vine.co/v/([^/]+)/?(</a>)$~';

这种模式可以匹配<a href="https://vine.co/v/iF20jKHvnqg" target="_blank">https://vine.co/v/iF20jKHvnqg</a>

替换字符串略有变化:

'<iframe src="https://vine.co/v/$2/embed/simple" width="480" height="480" frameborder="0"></iframe>'

所以我有这个测试脚本,它将替换你提到的iframe:的链接

<?php
$message = '<a href="https://vine.co/v/iF20jKHvnqg" target="_blank">https://vine.co/v/iF20jKHvnqg</a>';
$drc_embed_vine = '<iframe src="https://vine.co/v/$2/embed/simple" width="480" height="480" frameborder="0"></iframe>';
$pattern = '~^(<[^>]+>)https?://vine.co/v/([^/]+)/?(</a>)$~';
echo preg_replace($pattern, $drc_embed_vine, $message);

在我问的另一个问题中,它没有忽略尾部斜杠,只是将其全部删除。

$this->post['message'] = preg_replace('+/(["<])+', '$1', $this->post['message']);

rtrim无法工作,因为/不是字符串的最后一个。

下面是一个解析器示例:

$string = '<a href="https://vine.co/v/iF20jKHvnqg" target="_blank">https://vine.co/v/iF20jKHvnqg</a>';
$doc = new DOMDocument();
$doc->loadHTML($string);
$links = $doc->getElementsByTagName('a');
foreach($links as $link) {
    if(preg_match('~^https?://vine'.co/v/([^/]+)~', $link->getAttribute('href'), $url)){
        echo '<iframe src="https://vine.co/v/' . $url[1] . '/embed/simple" width="480" height="480" frameborder="0"></iframe>';
    }
}

输出:

<iframe src="https://vine.co/v/iF20jKHvnqg/embed/simple" width="480" height="480" frameborder="0"></iframe>

演示:https://eval.in/569642