2017-01-31 6 views
1

Что мне нужно сделать, это найти конкретный уникальный номер в тексте, который может возникать несколько раз в документе. Мне нужно отобразить все связанные с ним линии и все вхождения. Если вы проверите образец файла, вы увидите, что общий разделитель равен ===. Поэтому я подумывал использовать какое-то регулярное выражение, которое будет проверять искомый номер и отображать все строки между двумя ===. И с помощью preg_match запустите поиск по файлу. На данный момент я не знаю, как писать регулярные выражения, вы можете помочь мне с этим?PHP, как искать файл для определенной переменной и отображать все связанные с ним строки - см. Подробности

Файл просто:

======================================================= 
= Elapsed: yxz ms 
= In msg: <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><BLRequest xmlns="http://www.wwww.ww/wwww/"> *** <find_me>12345678901</find_me> *** </BLRequest></soapenv:Body></soapenv:Envelope> 
= Out msg: <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body xmlns:envelope="http://schemas.xmlsoap.org/soap/envelope/" envelope:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> *** </Body></Envelope> 
======================================================= 
======================================================= 
= Elapsed: yxz ms 
= In msg: <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><BLRequest xmlns="http://www.wwww.ww/wwww/"> *** <find_me>6545678901</find_me> *** </BLRequest></soapenv:Body></soapenv:Envelope> 
= Out msg: <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body xmlns:envelope="http://schemas.xmlsoap.org/soap/envelope/" envelope:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> *** </Body></Envelope> 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http " > *** </SOAP-ENV:Envelope> 
======================================================= 
======================================================= 
= Elapsed: yxz ms 
= In msg: <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><BLRequest xmlns="http://www.wwww.ww/wwww/"> *** <find_me>12345678901</find_me> *** </BLRequest></soapenv:Body></soapenv:Envelope> 
= Out msg: <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body xmlns:envelope="http://schemas.xmlsoap.org/soap/envelope/" envelope:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> *** </Body></Envelope> 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http " > *** </SOAP-ENV:Envelope> 
======================================================= 

Также я написал код, в котором должны быть это регулярное выражение будет вставлено, это нормально или есть лучший способ сделать это?

<?php 

$file ='myFile.log'; 
$search = '12345678901'; //find_me 
$pattern = '/(?<========================================================).*?(?========================================================)/s'; 


$file = fopen($file, "r") or die("Cannot open file!\n"); 
while ($line = fgets($file, 1024)) { 
    if (preg_match($pattern, $line)) { 
     echo "Results:</br> " . $line; 
    } else { 
     echo "No match: " . $line; 
    } 
} 
fclose($file); 

?> 

Обратите внимание, что: файл может быть до 200Мб. Текущий RE некорректен, это одна из моих попыток Кроме того, можно ли отображать результаты как xml? поскольку в файле есть xml строки?

+0

Do 'strpos ($ line, $ search)! == false' вместо' preg_match ($ pattern, $ line) 'и' возможно отображать результаты как xml' конечно, но это больше работает :-) – JustOnUnderMillions

+0

I была эта попытка, но она отображает только строку, где найден результат. 'while (! feof ($ fp)) { \t \t \t $ line = fgets ($ fp); \t \t \t если (! (StrPos ($ строка, $ игла) === ложь)) { \t \t \t \t \t \t \t \t \t эхо 'Найдено'. $ игла. ' в очереди #' . $ line_number. \t \t \t echo '
В этой строке содержатся:'. nl2br ($ строка); \t \t \t} ' – strumpf

ответ

1

Другим решением, которое имеет дело с большими файлами:

$filename = 'file.txt'; 
$search = '12345678901'; //find_me 
$pattern = "/(?<=====)(?:(?!====).)+($search)(?:(?!====).)+(?=====)/s"; 

$handle = fopen($filename , "r") or die("Cannot open $filename!\n"); 
$out = array(); 
$start = 0; 
$found = 0; 
while($line = fgets($handle)) { 
    if (preg_match('/^==========/', $line)) { 
     if ($start) { 
      if ($found) { 
       foreach($out as $ll) echo $ll,"\n"; 
      } 
      $found = 0; 
      $start = 0; 
      $out = []; 
     } else { 
      $start = 1; 
      $out[] = $line; 
     } 
    } else { 
     if ($start) { 
      $out[] = $line; 
      if (preg_match("/$search/", $line)) $found = 1; 
     } 
    } 

} 
fclose($handle); 

Выход:

======================================================= 

= Elapsed: yxz ms 

= In msg: <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><BLRequest xmlns="http://www.wwww.ww/wwww/"> *** <find_me>12345678901</find_me> *** </BLRequest></soapenv:Body></soapenv:Envelope> 

= Out msg: <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body xmlns:envelope="http://schemas.xmlsoap.org/soap/envelope/" envelope:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> *** </Body></Envelope> 

======================================================= 

= Elapsed: yxz ms 

= In msg: <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><BLRequest xmlns="http://www.wwww.ww/wwww/"> *** <find_me>12345678901</find_me> *** </BLRequest></soapenv:Body></soapenv:Envelope> 

= Out msg: <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body xmlns:envelope="http://schemas.xmlsoap.org/soap/envelope/" envelope:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> *** </Body></Envelope> 

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http " > *** </SOAP-ENV:Envelope> 
+0

спасибо за быстрый повтор. Я не получаю такой же результат.'================================================= ====== = Истекшее: 1 мс = В msg: *** 12345678901 *** = Out msg: *** ====================== ================================= Истекшее: 3 мс = В msg: *** 12345678901 *** = Out msg: *** *** 'Но если я меняю/n на
, то вывод будет отформатирован как ваш, и это нормально для меня. Хотя, как вы можете видеть, не все данные отображаются только в найденном номере. Если я запускаю это в исходном файле, я не получаю никакого вывода и не отображается ошибка. – strumpf

+0

@strumpf: 'fgets' читает файл по строкам (т. Е. Между двумя линиями), вы не можете использовать его для чтения строки, разделяются «
». Вы должны преобразовать '
' в '\ n' в файл перед его обработкой. – Toto

+0

это работает, спасибо. Но я все еще запутался в '
' и '\ n', потому что, если я использую' \ n', все находится в одной строке и разрывается в конце экрана и продолжается до другой строки. если я меняю его на 'foreach ($ out as $ ll) echo $ ll,"
";' output похож на ваш, с одним исключением xml-код не отображает только данные (что тоже нормально для меня) – strumpf

0

Я бы прочитал весь файл, затем протестировал его. Шаблон должен содержать поиск:

$filename = 'file.txt'; 
$search = '12345678901'; //find_me 
$pattern = "/(?<=====)(?:(?!====).)+($search)(?:(?!====).)+(?=====)/s"; 

$handle = fopen($filename , "r") or die("Cannot open $filename!\n"); 
$content = fread($handle, filesize($filename)); 
if (preg_match_all($pattern, $content, $matches)) { 
    print_r($matches); 
} else { 
    echo "No match: \n"; 
} 
fclose($handle); 

Выход:

Array 
(
    [0] => Array 
     (
      [0] => === 
= Elapsed: yxz ms 
= In msg: <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><BLRequest xmlns="http://www.wwww.ww/wwww/"> *** <find_me>12345678901</find_me> *** </BLRequest></soapenv:Body></soapenv:Envelope> 
= Out msg: <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body xmlns:envelope="http://schemas.xmlsoap.org/soap/envelope/" envelope:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> *** </Body></Envelope> 

      [1] => === 
= Elapsed: yxz ms 
= In msg: <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><BLRequest xmlns="http://www.wwww.ww/wwww/"> *** <find_me>12345678901</find_me> *** </BLRequest></soapenv:Body></soapenv:Envelope> 
= Out msg: <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body xmlns:envelope="http://schemas.xmlsoap.org/soap/envelope/" envelope:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> *** </Body></Envelope> 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http " > *** </SOAP-ENV:Envelope> 

     ) 

    [1] => Array 
     (
      [0] => 12345678901 
      [1] => 12345678901 
     ) 

) 
+0

Это очень полезно, но когда я запускаю это на исходном файле, я получаю фатальную ошибку - размер памяти исчерпан. Есть ли лучший способ сделать это и меньше потреблять память? Также лучший способ распечатать это без Array. Попытка сделать этот человек доступным для чтения как можно больше. – strumpf

+0

@strumpf: Извините, он не будет работать с большими файлами, потому что весь файл находится в памяти. Я приеду с другом ответом. – Toto