2017-02-10 19 views
0

Я пытаюсь разобрать: ческийpreg_match_all на удаленном содержимом

 
    //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); 

он возвращает пустой массив.

В любом случае, если я копирую/вставляю содержимое «$ calendar» в другую переменную и анализирую его с тем же регулярным выражением, он отлично работает.

Почему, когда я вызываю preg_match_all на ту же строку непосредственно из file_get_contents, он работает неправильно?

+0

Сохраняет ли uri файл с правильными заголовками файлов? Или даже контент. Попытайтесь повторить содержимое на странице. – Mouser

+0

Прежде всего print_r ваш $ calandar и проверьте, пусто или false –

+0

У меня что-то вроде * не удалось открыть поток: php_network_getaddresses: getaddrinfo failed * –

ответ

1

Удаленный файл использует последовательность CR LF как новую строку, поэтому якорь $ не соответствует. Когда вы копируете/вставляете содержимое файла в (или из) приложение, которое по умолчанию использует только LF в качестве новой строки, последовательность CR LF, вероятно, молча заменяется LF, и ваш шаблон работает.

несколько способов решить эту проблему:

1) написать явно возврат каретки в вашей схеме:

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

Если вы не хотите, возврат каретки в конце матча, использования trim или положите его в исходное утверждение: #^BEGIN:VEVENT.*?END:VEVENT(?=\r$)#sm. Вы также можете удалить $ и использовать псевдоним \R, который соответствует \r, \r\n и \n.

2) позволяют $ соответствовать независимо последовательности перевода строки с помощью директивы (*ANYCRLF)

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

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

$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; 
      } 
     } 
    } 
} 

Примечание: Вы можете аль поэтому используйте stream_get_line вместо fgets, так как он может возвращать строку без последовательности новой строки.

+0

Со вторым решением (* ANYCRLF) я решил все проблемы! Большое спасибо! – Infocurci