在regex中区分两个几乎相同的链接


differentiate between two almost identical links in regex

我创建了一个插件,可以将链接转换为链接处内容的Facebook嵌入版本。我的问题是,如果我禁用了插件的评论部分,那么评论的链接就会变成嵌入的帖子(如果插件的帖子部分仍然处于活动状态)。

让我们看看,所以我们有3个链接:

Facebook发布

<a href="https://www.facebook.com/zuck/posts/10102577175875681" target="_blank">ONE</a>

注释

<a href="https://www.facebook.com/zuck/posts/10102577175875681?comment_id=1193531464007751" target="_blank">Two</a>

以及对评论的回复

<a href="https://www.facebook.com/zuck/posts/10102577175875681?comment_id=1193531464007751&reply_comment_id=10102577641662241" target="_blank">Three</a>

所有三个链接都以开始

https://www.facebook.com/zuck/posts/10102577175875681

在下面的代码中,if条件是我的设置切换,并且这个帖子消息等于用户发布的内容,所以在这个例子中,这个帖子消息等同于上面的三个链接。

这是我创建的用于转换这些链接的插件。

if ($this->registry->options['drcae_facebook_comment_onoff']) {
  // swaps facebook comment links to embed code
  $drc_embed_facebook_cmt = '<div class="fb-comment-embed" data-include-parent="true" data-width="560" data-href="https://www.facebook.com/$3/posts/$4comment_id=$5"></div>';
  $this->post['message'] = preg_replace('~<a (.*)href="(.*)facebook.com/(.*)/posts/(.*)?comment_id=(.*)"(.*)<'/a>~', $drc_embed_facebook_cmt, $this->post['message']);
}
if ($this->registry->options['drcae_facebook_post_onoff']) {
  // swaps facebook post links to embed code
  $drc_embed_facebook_post = '<div class="fb-post" data-href="https://www.facebook.com/$3/posts/$4"></div>';
  $this->post['message'] = preg_replace('~<a (.*)href="(.*)facebook.com/(.*)/posts/(.*)"(.*)<'/a>~', $drc_embed_facebook_post, $this->post['message']);
}

我确实把它反过来了(帖子是第一个),但这导致评论嵌入了帖子,我通过先检查评论来绕过这一点,这可能不是最好的方法。

所以你可能已经注意到了我的regex,它不是最棒的,但这是我能够独自完成的工作,完全是regex的新手。

~<a (.*)href="(.*)facebook.com/(.*)/posts/(.*)"(.*)<'/a>~

我选择这样做我的正则表达式,所以如果链接的格式是这样的,它仍然会嵌入:

<a target="blank" href="https://www.facebook.com/USERNAME/posts/1234567890" alt="facebook post">LINK</a>

但现在我在事后猜测我的工作,在寻找但没有找到任何结果后,我想我会寻求一些帮助。

我如何区分这些链接,以便发布帖子,不干扰评论/评论回复?

更新1,嵌入帖子

现在我的插件看起来像这个

$drc_embed_facebook_post = '<div class="fb-post" data-href="https://www.facebook.com/$2/posts/$3"></div>';
$this->post['message'] = preg_replace('~<a (.*?)facebook'.com/([^/]+)/[^/]+/([0-9]+)(?:[?][^0-9]+([0-9]+)(?:&(.+))?)?</a>~', $drc_embed_facebook_post, $this->post['message']);

Regex特别是

~<a (.*?)facebook'.com/([^/]+)/[^/]+/([0-9]+)(?:[?][^0-9]+([0-9]+)(?:&(.+))?)?</a>~

我已经离开了一个懒惰的开始吗?我相信。。。不限制https://ect。。。(facebook之前的任何内容)

这在一定程度上起到了作用,这里有几个例子可以直接获取到帖子的链接。

https://www.facebook.com/RyanNewMe/posts/616837631826216?pnref=story
https://www.facebook.com/zuck/posts/10102833246942211?pnref=story
https://www.facebook.com/zuck/posts/10102830259184701?pnref=story

这些链接没有嵌入帖子。但是,如果我从它们中全部删除?pnref=story,则只有以下链接不起作用。

https://www.facebook.com/RyanNewMe/posts/616837631826216

我今天早些时候创建了一个漂亮、快速的正则表达式来提取href,所以我将使用它作为基线:

<a(?:'s*(?!href)[^'s>]*)*'s*href=["']([^"']+)

如果您使用这个正则表达式,您将获得href属性的任何值作为匹配项。例如:

https://www.facebook.com/zuck/posts/10102577175875681
https://www.facebook.com/zuck/posts/10102577175875681?comment_id=1193531464007751
https://www.facebook.com/zuck/posts/10102577175875681?comment_id=1193531464007751&reply_comment_id=10102577641662241

然后您可以解析此部分。

我做了这个正则表达式,它似乎可以工作:

facebook'.com/([^/]+)/[^/]+/([0-9]+)(?:[?][^0-9]+([0-9]+)(?:&(.+))?)?

您应该在$1$2$3$4中分别找到"zuck"、原始id、注释id和链接的整个其余部分的匹配项。(是的,我在最后得到了懒惰,你需要把链接的末尾解析成碎片吗?)

这看起来很复杂,但实际上可以理解。

  • facebook'.com/facebook.com/ 匹配

  • [^']+匹配一个或多个非斜线

  • ([0-9]+)捕获一个或多个数字

  • 这个blob:(?:[?][^0-9]+([0-9]+)(?:&(.+))?)?指定可选的扩展名(即结束的?s)。

    • (?:)表示非捕获组(主要是为了避免增加$2$3的名称)
    • [?][^0-9]+意味着后面有一个?,后面跟着一些非数字
    • ([0-9]+)捕获数字
    • CCD_ 20匹配CCD_ 21,然后捕获字符串的其余部分

编辑:关于你的更新,正则表达式可以这样修复(除非我错过了这个问题):

~<a (.*?)facebook'.com/([^/]+)/[^/]+/([0-9]+)(?:[?][^0-9<]+([0-9]*)(?:&([^<]+))?)?</a>~