Regex соответствует URL-адресу Youtube.

Я пытаюсь проверить URL Youtube с помощью regex:

preg_match('~http://youtube.com/watch\?v=[a-zA-Z0-9-]+~', $videoLink) 

Это вроде работает, но он может соответствовать URL-адресам, которые неверны. Например, это будет соответствовать ок:

 http://www.youtube.com/watch?v=Zu4WXiPRek 

Но так будет:

 http://www.youtube.com/watch?v=Zu4WX£&P!ek 

И это не будет:

 http://www.youtube.com/watch?v=!Zu4WX£&P4ek 

Я думаю, что это из-за оператора + . Это соответствует тому, что кажется первым символом после v= , когда ему нужно попробовать и сопоставить все за v= с помощью [a-zA-Z0-9-] . Любая помощь приветствуется, спасибо.

Проблема в том, что вам не требуется определенное количество символов в v = части URL. Так, например, проверка

 http://www.youtube.com/watch?v=Zu4WX£&P!ek 

будет соответствовать

 http://www.youtube.com/watch?v=Zu4WX 

и, следовательно, вернуть true. Вам нужно указать количество символов, которое вам нужно в v = part:

 preg_match('~http://youtube.com/watch\?v=[a-zA-Z0-9-]{10}~', $videoLink) 

или укажите, что группа [a-zA-Z0-9-] должна быть последней частью строки:

 preg_match('~http://youtube.com/watch\?v=[a-zA-Z0-9-]+$~', $videoLink) 

Ваш другой пример

 http://www.youtube.com/watch?v=!Zu4WX£&P4ek 

не соответствует, потому что знак + требует, чтобы по крайней мере один символ соответствовал [a-zA-Z0-9-].

Чтобы предоставить альтернативу, которая больше и гораздо менее элегантна, чем регулярное выражение, но работает с функциями PHP для парного разбора PHP, поэтому в долгосрочной перспективе это может быть немного более надежным:

  $url = "http://www.youtube.com/watch?v=Zu4WXiPRek"; $query_string = parse_url($url, PHP_URL_QUERY); // v=Zu4WXiPRek $query_string_parsed = array(); parse_str($query_string, $query_string_parsed); // an array with all GET params echo($query_string_parsed["v"]); // Will output Zu4WXiPRek that you can then // validate for [a-zA-Z0-9] using a regex 

Короткий ответ:

preg_match('%( http://www.youtube.com/watch \?v=(?:[a-zA-Z0-9-])+)(?:[&"\'\s])%', $videoLink)

Есть несколько предположений, сделанных здесь, поэтому позвольте мне объяснить:

  • Я добавил группу захвата ( ... ) вокруг всей http://www.youtube.com/watch?v=blah части ссылки, чтобы мы могли сказать: «Я хочу получить всю проверенную ссылку до и включая «v = movieHash»
  • Я добавил группу без захвата (?: ... ) вокруг вашего набора символов [a-zA-Z0-9-] и оставил знак + вне этого. Это позволит нам сопоставить все допустимые символы до определенной точки.
  • Самое главное, вам нужно сказать, как вы ожидаете, что ваша ссылка прекратится. Я предполагаю для вас (?:[&"\'\s])

    ?) Будет ли он в формате html (например, привязанный тег)? Если это так, ссылка в href , очевидно, закончится символом « или » .
    ?) Или, может быть, в строке запроса есть больше, поэтому будет значение & после значения v .
    ?) Возможно, есть пробел или разрыв строки после окончания ссылки \ s .

Важная часть состоит в том, что вы можете получить гораздо более точные результаты, если знаете, что окружает то, что вы ищете, как это имеет место со многими регулярными выражениями.

Эта группа, не участвующая в захвате (в которой я делаю предположения для вас), будет наноситься ударом по поиску и игнорированию всего лишнего мусора после того, что вас волнует («v = awesomeMovieHash»).

Результаты:

 http://www.youtube.com/watch?v=Zu4WXiPRek - Group 1 contains the http://www.youtube.com/watch?v=Zu4WXiPRek http://www.youtube.com/watch?v=Zu4WX&a=b - Group 1 contains http://www.youtube.com/watch?v=Zu4WX http://www.youtube.com/watch?v=!Zu4WX£&P4ek - No match a href="http://www.youtube.com/watch?v=Zu4WX&size=large" - Group 1 contains http://www.youtube.com/watch?v=Zu4WX http://www.youtube.com/watch?v=Zu4WX£&P!ek - No match 

«V = …» blob не гарантированно будет первым параметром в части запроса URL-адреса. Я бы рекомендовал использовать функцию parse_url () PHP, чтобы разбить URL-адрес на его составные части. Вы также можете собрать первоначальный URL-адрес, если кто-то начал строку с «https: //» или просто использовал «youtube.com» вместо «www.youtube.com» и т. Д.

 function get_youtube_vidid ($url) { $vidid = false; $valid_schemes = array ('http', 'https'); $valid_hosts = array ('www.youtube.com', 'youtube.com'); $valid_paths = array ('/watch'); $bits = parse_url ($url); if (! is_array ($bits)) { return false; } if (! (array_key_exists ('scheme', $bits) and array_key_exists ('host', $bits) and array_key_exists ('path', $bits) and array_key_exists ('query', $bits))) { return false; } if (! in_array ($bits['scheme'], $valid_schemes)) { return false; } if (! in_array ($bits['host'], $valid_hosts)) { return false; } if (! in_array ($bits['path'], $valid_paths)) { return false; } $querypairs = explode ('&', $bits['query']); if (count ($querypairs) < 1) { return false; } foreach ($querypairs as $querypair) { list ($key, $value) = explode ('=', $querypair); if ($key == 'v') { if (preg_match ('/^[a-zA-Z0-9\-_]+$/', $value)) { # Set the return value $vidid = $value; } } } return $vidid; } 

Следующее regex будет соответствовать любой ссылке youtube:

 $pattern='@(((http(s)?://(www\.)?)|(www\.)|\s)(youtu\.be|youtube\.com)/(embed/|v/|watch(\?v=|\?.+&v=|/))?([a-zA-Z0-9._\/~#&=;%+?-\!]+))@si';