正则表达式模式适用于字符串,但不适用于加载的文件内容

时间:2017-06-03 12:52:48

标签: php regex string preg-match file-get-contents

我想在“;”之间提取单词和XML文件中的“:”,例如“索引”这个词

  bla bla bla;指数:bla bla

该文件由其URL使用file_get_contents

加载
$output = file_get_contents("https://fr.wikipedia.org/wiki/Sp%C3%A9cial:Exporter/Base_de_donn%C3%A9es");

 preg_match_all('/\;.[a-zA-Z]+.\:/', $output, $matches, PREG_SET_ORDER, 0);
 var_dump($matches);

正则表达式模式使用regex101在同一文件内容上正常工作,并且当我在字符串变量中复制文本时也是如此。但上面的代码不起作用,它只返回最后一个匹配。

我做错了什么?

PS:我也尝试使用DOMDocument加载XML文件..结果相同。

1 个答案:

答案 0 :(得分:2)

一种内存占用少的方法,需要考虑几个因素:

  • 文件很大(不是很大但很大)。
  • 你正在处理xml文件的事实对于这种情况并不是很重要,因为你要查找的文本遵循它自己的基于行的格式XWiki format标准定义)这与xml格式无关。 但是,如果您绝对想在此处使用XML解析器来提取text标记内容,我建议使用XMLReader代替DOMDocument。
  • 您要查找的行始终是单行,以; (没有缩进)开头,并且下一行的:后面会紧随其后。

一旦看到(右键单击,源代码),您就可以选择逐行读取文件(而不是使用file_get_contents加载整个文件)并使用生成器功能选择有趣的行:

$url = 'https://fr.wikipedia.org/wiki/Sp%C3%A9cial:Exporter/Base_de_donn%C3%A9es';

$handle = fopen($url, 'rb');

function filterLines($handle) {
    while (feof($handle) !== true) {
        $line = fgets($handle);
        if ( $line[0] == ';' ) {
            $temp = $line;
            continue;
        } 
        if ( $line[0] == ':' && $temp )
            yield $temp;            

        $temp = false;
    }
}

foreach (filterLines($handle) as $line) {
    if ( preg_match_all('~\b\p{Latin}+(?: \p{Latin}+)*\b~u', $line, $matches) )
        echo implode(', ', $matches[0]), PHP_EOL;
}

fclose($handle);