【问题标题】:how to ignore the trailing slash in a preg replace如何忽略 preg 替换中的尾部斜杠
【发布时间】:2016-09-07 11:52:26
【问题描述】:

假设我在我的网站上发布了 2 个链接的变体...

(区别是尾随的/)

在我的网站上提交帖子后,它们会变成如下所示的超链接:

<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>~

但还是没有运气。

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

【问题讨论】:

  • 更好的用法是使用解析器。您可以对找到的第一个 URL 进行分组,然后检查 a 中的值是否与反向引用 \1 或您进行的任何分组相同。解析器会更干净,更不容易出错。 stackoverflow.com/questions/3577641/…
  • @user6188402 类似于https://vine.co/v/iF20jKHvnqg/,例如,我猜
  • 我只是问,因为我认为问题不是 link,而是与输入不匹配的正则表达式的另一部分
  • 我也认为问题在于模式,无法匹配这样的链接......我花了一点时间才弄清楚是什么让我感到困惑
  • 另外,我不确定在这种情况下是否需要正则表达式:结果字符串完全包含源字符串。剥离最终的斜杠并连接就足够了,或者只使用 sprintf。

标签: php regex replace preg-replace vine


【解决方案1】:

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

$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-&gt;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>)$~';

此模式可以匹配&lt;a href="https://vine.co/v/iF20jKHvnqg" target="_blank"&gt;https://vine.co/v/iF20jKHvnqg&lt;/a&gt;

替换字符串略有变化:

'<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);

【讨论】:

  • 所以我没有提到我的链接,一旦提交就自动变成超链接,I.E. &lt;a href="https://vine.co/v/iF20jKHvnqg" target="_blank"&gt;https://vine.co/v/iF20jKHvnqg&lt;/a&gt; 这将是消息变量,我已将其添加到原始帖子中。但是基于这个答案,我对其进行了修改,并为我的替换提出了~&lt;a href="https?://vine.co/v/([^/]+)/?~" target="_blank"&gt;https?://vine.co/v/([^/]+)/?&lt;\/a&gt;~,这没有用。
  • 我也是正则表达式的新手,所以我并没有真正理解其中的大部分内容,我只是看到代码和其中的一部分是有意义的,哈哈
  • 我在插件的开头也试过$this-&gt;post['message'] = rtrim($this-&gt;post['message'], '/');$post['message'] = rtrim($post['message'], '/');,但这也没有用
  • 所以如果我理解的话,用户提交了一个 Vine 视频 URL,它会自动成为一个链接,而您获得的正是这个链​​接并且想要转换为 iframe?如果我是对的,您无法完全控制用户提交:您无法获取 URL,只有 URL 转换后的链接?后面的斜线呢?如果用户提交带有斜杠的 URL,它是否也存在于链接中?
  • 确切地说,如果用户发布vine.com/v/50471385,HL 将是这样的,如果它带有尾部斜杠,则 HL 将带有尾部斜杠。我试过你的代码,这对我不起作用,我发布的原始代码有效,它只是没有检测到是否有结束斜线。
【解决方案2】:

这是一个解析器示例:

$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

【讨论】:

    【解决方案3】:

    在我问的另一个问题中回答,它不会忽略尾部斜杠,而是将其全部删除。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-09
      • 1970-01-01
      • 2019-09-03
      • 1970-01-01
      • 2020-08-29
      相关资源
      最近更新 更多