Реггекс не соответствует правилу "иногда" - PullRequest
0 голосов
/ 01 января 2011

У меня есть preg_match_all с регулярным выражением, которое должно взять номер видео YouTube и поместить его в массив, так что чем больше видео на YouTube, тем больше массивов он создает.Вот верный результат:

C1

Array ( [0] => j5-yKhDd64s ) 1Array ( [0] => j5-yKhDd64s ) 1Array ( [0] => j5-yKhDd64s ) 1 

Теперь моя проблема иногда возникает:

C2

Array ( [0] => _dKtoRU7Tlk http://www.youtube.com/watch?v=_dKtoRU7Tlk http://www.youtube.com/watch?v=_dKtoRU7Tlk ) 1 

Видите разницу?На C1 он правильно идентифицирует идентификатор видео в архивах и, таким образом, C2 захватывает один, а затем дает сбой и переносит остальное в массив.

Ссылки на YouTube C1 были такими:

http://www.youtube.com/watch?v=j5-yKhDd64s&feature=email&email=comment_reply_received http://www.youtube.com/watch?v=j5-yKhDd64s&feature=email&email=comment_reply_received http://www.youtube.com/watch?v=j5-yKhDd64s&feature=email&email=comment_reply_received

Ссылки C2 на YouTube были такими:

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

разница в том, что естьфункция & ... в C1 .Я думаю, потому что мое регулярное выражение не является полностью оптимальным?

    if (preg_match_all("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=[0-9]/)[^&\n]+|(?<=v=)[^&\n]+#", $content, $matches, PREG_SET_ORDER)) {
      foreach($matches as $m) {
   echo print_r($m);
      }
    }
    $nContent = preg_replace("#(?:https?://)?(?:www\.)?youtube\.com/(?:[^\s]*)#", '', $content);
    echo $nContent; 

Как я могу это исправить?Спасибо!

Ответы [ 3 ]

3 голосов
/ 01 января 2011

Ваше регулярное выражение:

#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=[0-9]/)[^&\n]+|(?<=v=)[^&\n]+#

сводится к трем альтернативным частям:

(?<=v=)[a-zA-Z0-9-]+(?=&)
(?<=[0-9]/)[^&\n]+
(?<=v=)[^&\n]+

(?<=...) называется утверждением-зазором, и в двух из этих частей вы видите, что оно выглядитдля v=.

В первом варианте он ищет [a-zA-Z0-9-]+, за которым следует &.(что является предварительным утверждением: (?=...))

Вторая альтернатива в данном случае не применима.

В третьей альтернативе она ищет что-либо до тех пор, пока не нажмет & или \n.

Ваш пример не подходит ни к одному из них.Самым простым решением было бы изменить последнюю часть:

(?<=v=)[^&\n]+

на

(?<=v=)[^&\s]+

, чтобы оно прекратило сопоставление на & или любом пустом месте (\s).

Или лучший совет: просто перепишите все это, чтобы действительно разобрать URL обычным способом, сохраняя некоторые головные боли в будущем.

2 голосов
/ 01 января 2011

После ответов и комментариев mvds:

$parsed_url = parse_url("http://www.youtube.com/watch?v=j5-yKhDd64s&feature=email&email=comment_reply_received");
parse_str($parsed_url["query"],$output);
echo $output['v'];
0 голосов
/ 01 января 2011

Редактировать: этот файл вылавливает любую ссылку на видео на YouTube, изменил ее так, чтобы он останавливался на пробелах, переносе строки или "&"

надеюсь, что это даст вам начало

"{youtube.com/watch[?]v=([a-z0-9_-]*?)[^&\s]+}i"
...