2017-02-10 1 views
0

je tente d'analyser un iCal:preg_match_all sur le contenu à distance

 
    //open file 
    $calendar = file_get_contents('http://app.kigo.net/public/ics.php?c-7ca2eb67c1a7fa8b87b2434ed1096076-422-9871b35967bb29f999cd11ac72943011'); 
    //debug purpose 
    echo $calendar; 
    //parse string 
    preg_match_all('#^BEGIN\:VEVENT.*?END\:VEVENT$#sm',$calendar,$results,PREG_SET_ORDER); 
    //output: empty! 
    print_r($results); 

retourne un tableau vide. Quoi qu'il en soit, si je copie/colle le contenu "$ calendar" sur une autre variable, et l'analyse avec la même expression rationnelle, cela fonctionne très bien. Pourquoi quand j'appelle preg_match_all sur même chaîne directement à partir de file_get_contents, cela fonctionne mal?

+0

Est-ce que l'uri retourne un fichier avec les en-têtes de fichier corrects? Ou même le contenu. Essayez d'écho le contenu dans la page. – Mouser

+0

Tout d'abord print_r votre $ calandar et vérifiez si vide ou faux –

+0

J'ai quelque chose comme * n'a pas réussi à ouvrir le flux: php_network_getaddresses: getaddrinfo échoué * –

Répondre

1

Le fichier distant utilise la séquence CR LF comme nouvelle ligne, c'est pourquoi l'ancre $ ne correspond pas. Lorsque vous copiez/collez le contenu du fichier à (ou à partir) d'une application qui n'utilise par défaut que LF en tant que nouvelle ligne, la séquence CR LF est probablement remplacé par LF et votre modèle fonctionne.

Plusieurs façons de résoudre le problème:

1) explicitement le retour chariot dans votre modèle:

#^BEGIN:VEVENT.*?END:VEVENT\r$#sm 

Si vous ne voulez pas le retour chariot à la fin du match, l'utilisation trim ou le mettre dans une assertion lookahead: #^BEGIN:VEVENT.*?END:VEVENT(?=\r$)#sm. Vous pouvez également supprimer le $ et utiliser l'alias \R correspondant à \r, \r\n et \n.

2) permettent à l'$ pour correspondre à ce que la séquence de retour à la ligne en utilisant la directive (*ANYCRLF)

#(*ANYCRLF)^BEGIN:VEVENT.*?END:VEVENT$#sm 

3) ne pas utiliser un modèle tout (après tout ce que vous cherchez seulement pour les blocs entre les lignes fixes, et si votre fichier peut être un peu long, il est plus élégant et économise de la mémoire pour lire votre fichier en ligne et d'utiliser un générateur pour revenir blocs):

$filePath = 'http://app.kigo.net/public/ics.php?c-7ca2eb67c1a7fa8b87b2434ed1096076-422-9871b35967bb29f999cd11ac72943011'; 

try { 
    if (false === $fp = fopen($filePath, 'rb')) 
     throw new Exception('Could not open the file!'); 

} catch (Exception $e) { 
    echo 'Error (File: ' . $e->getFile() . ', line ' . $e->getLine() . '): ' . $e->getMessage(); 
} 

foreach (genBlocks($fp, "BEGIN:VEVENT\r\n", "END:VEVENT\r\n") as $block) { 
    echo $block . PHP_EOL; 
} 

fclose($fp); 

function genBlocks($fp, $start, $end, $buffer = 1024) { 
    $block = false; 
    while (false !== $line = fgets($fp, $buffer)) { 
     if ($line === $start) { 
      $block = $line; 
     } elseif ($block !== false) { 
      $block .= $line; 
      if ($line === $end) { 
       yield $block; 
       $block = false; 
      } 
     } 
    } 
} 

note: Vous pouvez al donc utilisez stream_get_line au lieu de fgets puisque celui-ci est capable de retourner une ligne sans la nouvelle ligne.

+0

Avec la deuxième solution (* ANYCRLF) j'ai résolu tous les problèmes! Merci beaucoup vraiment! – Infocurci