为什么此正则表达式适用于一个 Url 但不适用于另一个?
Why Does This Regex Work On One Url But Not Another?
所以我使用这个正则表达式将所有帖子从 Twitter 转换为嵌入的推文:
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?twitter\.com/([^&]+)/status/([^&]+)\S*~i'
但是当我尝试为 Instagram 或 Facebook 做同样的事情时,它不起作用:
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?instagram\.com/p/([^&]+)\S*~i'
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?facebook\.com/([^&]+)/posts/([^&]+)\S*~i'
正则表达式几乎完全相同,twitter 链接几乎与 facebook 链接相同,例如https://twitter.com/USER/status/idnumber
https://www.facebook.com/USER/posts/idnumber
。 Instagram 的功能几乎相同,但像这样 https://www.instagram.com/p/id
我之所以在正则表达式的开头使用 ~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|
是因为我的网站上有 BBCode,你可以看到我之前关于正则表达式的问题
编辑:
这是完整的正则表达式和替换:
$search = array (
'~\[b](.*?)\[/b]~is',
'~\[i](.*?)\[/i]~is',
'~\[u](.*?)\[/u]~is',
'~\[ul](.*?)\[/ul]~is',
'~\[li](.*?)\[/li]~is',
'~\[user=(.*?)](.*?)\[/user]~i',
'~\[url=https?.*?(?:[/?&](?:e|vi?|ci)(?:[/=]|%3D)|youtu\.be/|embed/|/user/[^/]+#p/(?:[^/]+/)+)([\w-]{10,12})].*?\[/url]~i',
'~\[url]https?.*?(?:[/?&](?:e|vi?|ci)(?:[/=]|%3D)|youtu\.be/|embed/|/user/[^/]+#p/(?:[^/]+/)+)([\w-]{10,12}).*?\[/url]~i',
'~\[url=((?:ht|f)tps?://[a-z\d.-]+\.[a-z]{2,3}/\S*?)](.*?)\[/url]~i',
'~\[url]((?:ht|f)tps?://[a-z\d.-]+\.[a-z]{2,3}/\S*?)\[/url]~i',
'~\[img=(.*?)].*?\[/img]~i',
'~\[quote](.*?)\[/quote]~is',
'~\[code](.*?)\[/code]~is',
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|(?:\bhttps?.*?(?:[/?&](?:e|vi?|ci)(?:[/=]|%3D)|youtu\.be/|embed/|/user/[^/]+#p/(?:[^/]+/)+)([\w-]{10,12}))\S*~i',
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?clips\.twitch\.tv/([^&]+)\S*~i',
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?imgur\.com/gallery/([^&]+)\S*~i',
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?twitter\.com/([^&]+)/status/([^&]+)\S*~i',
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?facebook\.com/([^&]+)/posts/([^&]+)\S*~i',
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://.+?(?=\s|$)~im'
);
$replace = array (
'<strong></strong>',
'<em></em>',
'<u></u>',
'<ul></ul>',
'<li></li>',
'<a href="../login/profile?u=" target="_blank"></a>',
'<br><iframe width="600" height="315" src="//www.youtube.com/embed/" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><br>',
'<br><iframe width="600" height="315" src="//www.youtube.com/embed/" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><br>',
'<a href="" target="_blank" rel="nofollow"></a>',
'<a href="" target="_blank" rel="nofollow"></a>',
'<img src=""></img>',
'<quote></quote>',
'<code></code>',
'<br><iframe width="600" height="315" src="//www.youtube.com/embed/" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><br>',
'<br><iframe width="600" height="315" src="//clips.twitch.tv/embed?clip=&autoplay=false" frameborder="0" allowfullscreen></iframe><br>',
'<blockquote class="imgur-embed-pub" lang="en" data-id=""><a href="//www.imgur.com/"></a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>',
'<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr"><a href="//twitter.com//status/?ref_src=twsrc%5Etfw"></a></blockquote><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>',
'<iframe src="//www.facebook.com/plugins/post.php?href=//www.facebook.com//posts/&width=500" width="500" height="705" style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true" allow="encrypted-media"></iframe>',
'<a href="[=11=]" target="_blank" rel="nofollow">[=11=]</a>'
);
在不知道您试图从中提取的一些示例 url 的情况下,很难绝对肯定地说,但也许我可以提供一些一般性建议。
([^&]+)
<-- 这将捕获一个或多个非&符号字符。这个“贪婪限定符 (+
) 将匹配并匹配多行上的白色 space 和可见字符,直到它找到下一个 &
或字符串的末尾! ...显然不是你想要的。
如果要确保没有&
、?
、#
个字符,可以使用([^&?#]+)
。但是,这也可能消耗太多,因为如果 url 不包含任何这些字符,则正则表达式引擎将匹配太多。
如果您不确定将存在的字符,但您知道它们将是 "visible" 个字符,您可以使用 \S+
.
最后,您可以像这样将白色-space 字符添加到您的 "negated character class" 中:([^&?#\s]+)
通过使用最后一个字符,您可以紧随其后 \S*
这将 match/consume 零个或多个尾随可见字符 - 这将确保整个 url 被替换并且您只得到您正在寻找的 "white meat"。
所以我使用这个正则表达式将所有帖子从 Twitter 转换为嵌入的推文:
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?twitter\.com/([^&]+)/status/([^&]+)\S*~i'
但是当我尝试为 Instagram 或 Facebook 做同样的事情时,它不起作用:
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?instagram\.com/p/([^&]+)\S*~i'
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?facebook\.com/([^&]+)/posts/([^&]+)\S*~i'
正则表达式几乎完全相同,twitter 链接几乎与 facebook 链接相同,例如https://twitter.com/USER/status/idnumber
https://www.facebook.com/USER/posts/idnumber
。 Instagram 的功能几乎相同,但像这样 https://www.instagram.com/p/id
我之所以在正则表达式的开头使用 ~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|
是因为我的网站上有 BBCode,你可以看到我之前关于正则表达式的问题
编辑:
这是完整的正则表达式和替换:
$search = array (
'~\[b](.*?)\[/b]~is',
'~\[i](.*?)\[/i]~is',
'~\[u](.*?)\[/u]~is',
'~\[ul](.*?)\[/ul]~is',
'~\[li](.*?)\[/li]~is',
'~\[user=(.*?)](.*?)\[/user]~i',
'~\[url=https?.*?(?:[/?&](?:e|vi?|ci)(?:[/=]|%3D)|youtu\.be/|embed/|/user/[^/]+#p/(?:[^/]+/)+)([\w-]{10,12})].*?\[/url]~i',
'~\[url]https?.*?(?:[/?&](?:e|vi?|ci)(?:[/=]|%3D)|youtu\.be/|embed/|/user/[^/]+#p/(?:[^/]+/)+)([\w-]{10,12}).*?\[/url]~i',
'~\[url=((?:ht|f)tps?://[a-z\d.-]+\.[a-z]{2,3}/\S*?)](.*?)\[/url]~i',
'~\[url]((?:ht|f)tps?://[a-z\d.-]+\.[a-z]{2,3}/\S*?)\[/url]~i',
'~\[img=(.*?)].*?\[/img]~i',
'~\[quote](.*?)\[/quote]~is',
'~\[code](.*?)\[/code]~is',
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|(?:\bhttps?.*?(?:[/?&](?:e|vi?|ci)(?:[/=]|%3D)|youtu\.be/|embed/|/user/[^/]+#p/(?:[^/]+/)+)([\w-]{10,12}))\S*~i',
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?clips\.twitch\.tv/([^&]+)\S*~i',
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?imgur\.com/gallery/([^&]+)\S*~i',
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?twitter\.com/([^&]+)/status/([^&]+)\S*~i',
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?facebook\.com/([^&]+)/posts/([^&]+)\S*~i',
'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://.+?(?=\s|$)~im'
);
$replace = array (
'<strong></strong>',
'<em></em>',
'<u></u>',
'<ul></ul>',
'<li></li>',
'<a href="../login/profile?u=" target="_blank"></a>',
'<br><iframe width="600" height="315" src="//www.youtube.com/embed/" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><br>',
'<br><iframe width="600" height="315" src="//www.youtube.com/embed/" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><br>',
'<a href="" target="_blank" rel="nofollow"></a>',
'<a href="" target="_blank" rel="nofollow"></a>',
'<img src=""></img>',
'<quote></quote>',
'<code></code>',
'<br><iframe width="600" height="315" src="//www.youtube.com/embed/" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><br>',
'<br><iframe width="600" height="315" src="//clips.twitch.tv/embed?clip=&autoplay=false" frameborder="0" allowfullscreen></iframe><br>',
'<blockquote class="imgur-embed-pub" lang="en" data-id=""><a href="//www.imgur.com/"></a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>',
'<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr"><a href="//twitter.com//status/?ref_src=twsrc%5Etfw"></a></blockquote><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>',
'<iframe src="//www.facebook.com/plugins/post.php?href=//www.facebook.com//posts/&width=500" width="500" height="705" style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true" allow="encrypted-media"></iframe>',
'<a href="[=11=]" target="_blank" rel="nofollow">[=11=]</a>'
);
在不知道您试图从中提取的一些示例 url 的情况下,很难绝对肯定地说,但也许我可以提供一些一般性建议。
([^&]+)
<-- 这将捕获一个或多个非&符号字符。这个“贪婪限定符 (+
) 将匹配并匹配多行上的白色 space 和可见字符,直到它找到下一个 &
或字符串的末尾! ...显然不是你想要的。
如果要确保没有&
、?
、#
个字符,可以使用([^&?#]+)
。但是,这也可能消耗太多,因为如果 url 不包含任何这些字符,则正则表达式引擎将匹配太多。
如果您不确定将存在的字符,但您知道它们将是 "visible" 个字符,您可以使用 \S+
.
最后,您可以像这样将白色-space 字符添加到您的 "negated character class" 中:([^&?#\s]+)
通过使用最后一个字符,您可以紧随其后 \S*
这将 match/consume 零个或多个尾随可见字符 - 这将确保整个 url 被替换并且您只得到您正在寻找的 "white meat"。