2011-01-01 2 views
0

J'ai un preg_match_all avec une regexpression, qui devrait prendre un numéro de vidéo youtube et le placer dans le tableau, donc plus il ya de vidéos youtube, plus il y a de tableaux. Voilà le résultat, qui sont corrects:Regex pregmatch pas correct "parfois"

C1

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

Maintenant, mon problème est parfois cela se produit:

C2

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

Voir la différence? À C1 il prend l'id vidéo correcte dans les ararys et ainsi, le C2 attrape un puis échoue et prend le reste dans le tableau.

Les C1 liens youtube était comme ça:

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

Les C2 liens youtube était comme ça:

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

la différence est qu'il ya la fonction & ... dans le C1. Je pense que c'est parce que mon regex n'est pas complètement optimale?

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; 

Comment puis-je résoudre ce problème? Je vous remercie!

Répondre

3

Votre regexp:

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

se résume à trois parties alternatives:

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

Le (?<=...) est appelé une affirmation et lookbehind dans deux de ces pièces que vous voyez il recherche v=. Dans la première alternative, il recherche [a-zA-Z0-9-]+ suivi de &. (qui est une assertion de lookahead: (?=...))

La deuxième alternative ne s'applique pas dans ce cas. Dans la troisième variante, il cherche n'importe quoi jusqu'à ce qu'il obtienne & ou \n.

Votre exemple ne correspond pas correctement à l'un de ceux-ci. Le moyen le plus fixe serait de changer la dernière partie:

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

à

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

il arrêtera correspondant sur & ou les espaces blancs (\s).

Ou un meilleur conseil: il suffit de réécrire le tout pour vraiment analyser l'URL d'une manière normale, en sauvant des maux de tête à l'avenir.

+0

Merci! J'aimerais en savoir un peu plus sur ce que vous pensiez du dernier "meilleur" conseil. "Parse l'url d'une manière normale", que voulez-vous dire par là, petit exemple? – Karem

+0

@Karem: E.g. en faisant correspondre des url entières du texte ('#http: // [^ \ s] + #') et en regardant http://php.net/manual/fr/function.parse-url.php, puis la partie query et utilisez 'parse_str' pour le diviser en vars séparés. – mvds

+0

Donc, vous voulez dire par premier match s'il ya un lien, puis prenez le lien prendre une requête et prendre? V pour obtenir le lien vidéo .. correct? – Karem

0

Edit: celui-ci repêche tout lien vidéo youtube, changé de sorte qu'il arrête sur les espaces, saut de ligne ou « & »

espère que cela vous donne un début

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

Après la réponse de MVDS et commentaires:

$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

Merci! Et @Karem, pour obtenir les urls à partir de n'importe quel texte , utilisez 'preg_match_all (" #http: // [^ \ s] + # i ", $ txt, $ correspond à), puis bouclez l'extrait ci-dessus sur les correspondances en utilisant' foreach ($ matches [0] as $ url) {...} ' – mvds

Questions connexes