我有一个文本字段,用户可以在其中写入任何内容.

例如:

Lorem Ipsum只是一个虚拟文本.

现在我想解析它,找到所有YouTube视频URL和它们的ID.

知道这是怎么回事吗?

推荐答案

YouTube视频URL可能有多种格式:

  • 最新短格式:http://youtu.be/NLqAF9hrVbY
  • iframe:http://www.youtube.com/embed/NLqAF9hrVbY
  • IFRAME(安全):https://www.youtube.com/embed/NLqAF9hrVbY
  • 对象参数:http://www.youtube.com/v/NLqAF9hrVbY?fs=1&hl=en_US
  • 对象嵌入:http://www.youtube.com/v/NLqAF9hrVbY?fs=1&hl=en_US
  • 手表:http://www.youtube.com/watch?v=NLqAF9hrVbY
  • 用户:http://www.youtube.com/user/Scobleizer#p/u/1/1p3vcRhsYGo
  • 放映室:http://www.youtube.com/ytscreeningroom?v=NRHVzbJVx8I
  • 任何事都可以http://www.youtube.com/sandalsResorts#p/c/54B8C800269D7C1B/2/PPS-8DMrAn4
  • 任何/子域/太:http://gdata.youtube.com/feeds/api/videos/NLqAF9hrVbY
  • 更多参数:http://www.youtube.com/watch?v=spDj54kf-vY&feature=g-vrec
  • 查询可能包含点:http://www.youtube.com/watch?v=spDj54kf-vY&feature=youtu.be
  • 无cookie域:http://www.youtube-nocookie.com

下面是一个带有注释正则表达式的PHP函数,它匹配每个URL表单,并将它们转换为链接(如果它们还不是链接):

// Linkify youtube URLs which are not already links.
function linkifyYouTubeURLs($text) {
    $text = preg_replace('~(?#!js YouTubeId Rev:20160125_1800)
        # Match non-linked youtube URL in the wild. (Rev:20130823)
        https?://          # Required scheme. Either http or https.
        (?:[0-9A-Z-]+\.)?  # Optional subdomain.
        (?:                # Group host alternatives.
          youtu\.be/       # Either youtu.be,
        | youtube          # or youtube.com or
          (?:-nocookie)?   # youtube-nocookie.com
          \.com            # followed by
          \S*?             # Allow anything up to VIDEO_ID,
          [^\w\s-]         # but char before ID is non-ID char.
        )                  # End host alternatives.
        ([\w-]{11})        # $1: VIDEO_ID is exactly 11 chars.
        (?=[^\w-]|$)       # Assert next char is non-ID or EOS.
        (?!                # Assert URL is not pre-linked.
          [?=&+%\w.-]*     # Allow URL (query) remainder.
          (?:              # Group pre-linked alternatives.
            [\'"][^<>]*>   # Either inside a start tag,
          | </a>           # or inside <a> element text contents.
          )                # End recognized pre-linked alts.
        )                  # End negative lookahead assertion.
        [?=&+%\w.-]*       # Consume any URL (query) remainder.
        ~ix', '<a href="http://www.youtube.com/watch?v=$1">YouTube link: $1</a>',
        $text);
    return $text;
}

; // 结束$YouTubeId.

下面是一个与regex完全相同的JavaScript版本(删除注释):

// Linkify youtube URLs which are not already links.
function linkifyYouTubeURLs(text) {
    var re = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube(?:-nocookie)?\.com\S*?[^\w\s-])([\w-]{11})(?=[^\w-]|$)(?![?=&+%\w.-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig;
    return text.replace(re,
        '<a href="http://www.youtube.com/watch?v=$1">YouTube link: $1</a>');
}

Notes:

  • URL的VIDEO_ID部分被捕获在一个且唯一的捕获组:$1中.
  • 如果您知道您的文本不包含任何预链接的URL,那么您可以安全地删除测试此条件的负面先行断言(以注释:"Assert URL is not pre-linked."开头的断言).这将略微加快正则表达式的速度.
  • 可以根据需要修改替换字符串.上面提供的方法只是创建一个指向通用"http://www.youtube.com/watch?v=VIDEO_ID"样式URL的链接,并将链接文本设置为:"YouTube link: VIDEO_ID".

Edit 2011-07-05:在ID char类中添加了-个连字符

Edit 2011-07-17:修正了regex使用YouTube ID之后URL的任何剩余部分(例如query)的问题.添加了'i' ignore-case修饰符.将函数重命名为camelCase.改进的预链接前瞻测试.

Edit 2011-07-27:增加了新的"user"和"ytcreeningroom"格式的YouTube URL.

Edit 2011-08-02:个简化/泛化以处理新的"任何/事物/go "YouTube URL.

Edit 2011-08-25:.一些修改:

  • 添加了:linkifyYouTubeURLs()函数的Javascript版本.
  • 以前的版本中,scheme(HTTP协议)部分是可选的,因此会匹配无效的URL.使计划成为必需的一部分.
  • 以前的版本在视频ID周围使用了\b个单词的边界锚.但是,如果视频ID以-破折号开始或结束,这将不起作用.已修复,因此它可以处理这种情况.
  • 更改了VIDEO_ID表达式,使其长度必须正好为11个字符.
  • 如果预先链接的URL在VIDEO_ID之后有查询字符串,则以前的版本无法排除这些URL.改进了负前视断言以修复此问题.
  • +%添加到匹配查询字符串的字符类中.
  • 将PHP版本正则表达式分隔符从:%更改为:~.
  • 添加了一个"注释"部分,其中包含一些方便的注释.

Edit 2011-10-12: YouTube URL主机部分现在可以有任何子域(不仅仅是www.个).

Edit 2012-05-01:"消费URL"部分现在可能允许使用"-".

Edit 2013-08-23:增加了@Mei提供的附加格式.(查询部分可以有一个.点.

Edit 2013-11-30:增加了@Cronus:youtube-nocookie.com提供的附加格式.

Edit 2016-01-25:修复了处理CRONUS提供的错误 case 的正则表达式.

Php相关问答推荐

发送给WooCommerce中相关产品作者的通知新订单的邮箱

谷歌云SQL / mysql谁是对的?

让所有具有相同名称的产品在WooCommerce中更改价格

如何删除Foreach语句中的重复值?

为什么只有最后一次点击的点赞/心形会按预期改变 colored颜色 ,而其他的保持正常 colored颜色 ?

Laravel服务Provider 没有向服务类注入价值

无法在Laravel中将日志(log)通道设置为空

PHP Match如何准确判断条件?

htaccess 配置提供静态文件和动态文件

Filament PHP v3:在禁用的表单字段上,ID 不会写入数据库

奇怪的 preg_match_all() 行为

woocommerce checkout 页面上的自定义字段

计算添加到购物车的点击次数并将其显示在 WooCommerce 管理产品列表中

在 vue 自定义渲染器中访问变量

Symfony:指定 data_class 时,提交的表单获取初始化前不得访问

Laravel Eloquent:复杂的多对多关系以及缺失关系的默认值

PHP文件如何从CSS执行

如何用 php ML 解决这个问题?

Laravel 测试 assertJsonMissing 不适用于唯一的键.为什么?

PHP 中的正则表达式,具有字符范围,但不包括特定字符