Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Wyszukiwanie w pliku logu
Forum PHP.pl > Forum > Przedszkole
Qwer
Witam,

mam plik logu pewnej gry, przykładowa linijka wygląda tak:
[30 Nov 11:53:09] PARTY [Caelldfssion] jakiś tam tekst

no i mam takie pliki utworzone przez siebie:
dictionary.txt (słownik) o przykładowej zawartości:
.*kur.* (na razie jeden wyraz)

oraz channels.txt (schematy kanałów do przeglądania) i przykładowej zawartości:
^\[.. ... ..:..:..\] PARTY \[.*\]
^\[.. ... ..:..:..\] ALL [\[.*\]
^\[.. ... ..:..:..\] ALLIANCE \[.*\]
^\[.. ... ..:..:..\] TRADE \[.*\]
^\[.. ... ..:..:..\] HERO_VOICE \[.*\]

i teraz sedno problemu... stworzyłem skrypt, który niestety nie działa i bardzo obciąża sprzęt bo wyszukuje w 30MB pliku (około 400000 linijek) i dla każdej jest odpowiednia ilość kombinacji wyszukiwania, dla w/w plików jest to 5^1 kombinacji (5), skrypt wygląda tak jak kod poniżej, jeżeli ktoś ma pomysł jak to dobrze rozwiązać aby działało i nie obciążało aż tak sprzętu to prosiłbym o pomoc

skrypt:
  1. <?php
  2. $channels=file('channels.txt');
  3. $dictionary=file('dictionary.txt');
  4. $file=fopen('chat.log', 'r');
  5. $search;
  6. $founded;
  7. $k=0;
  8.  
  9. for ($i=0; $i<sizeof($channels); $i++){
  10. for ($j=0; $j<sizeof($dictionary); $j++){
  11. $search[$k]=trim($channels[$i])." ".trim($dictionary[$j]);
  12. $k++;
  13. }
  14. }
  15.  
  16.  
  17. while(!feof($file)){
  18. $row=fgets($file);
  19. for($i=0; $i<sizeof($search); $i++){
  20. if (preg_match("/$search[$i]/i", $row)){
  21. if (sizeof($founded) != 0){
  22. $founded[sizeof($founded)+1]=$row;
  23. } else {
  24. $founded[0]=$row;
  25. }
  26. }
  27. }
  28.  
  29. }
  30.  
  31. for($i=0; $i<sizeof($founded); $i++){
  32. echo $founded[$i]."<br>";
  33. }
  34. ?>

wcześniej wczytałem cały 30MB plik do tablicy funkcją file() i nie było to dobre rozwiązanie, także obciążało, stąd chciałem przesiąść się na to, ale jak widać nieskutecznie.
W kodzie mogą być drobne błędy jednak całość powinna być w miarę dobrze zrozumiana. Z góry dziękuję za pomoc.
Pilsener
1. To, co ma być znalezione wrzucasz do tablicy:
  1. $slownik = file('plik.txt');
- file, lub korzystając z while + feof + fgets

2. Następnie parsujesz plik:
  1. $uchwyt = fopen($pliczek,'r');
  2. while(!feof($uchwyt)){
  3. ++$licznik;
  4. $linia = rtrim(fgets($uchwyt)));
  5. foreach($slownik as $line){
  6. $line2 = rtrim($line);
  7. if(strstr($linia,$line2)){
  8. $znaleziono = 1;
  9. break;
  10. }
  11. }
  12. if($znaleziono==1){
  13. echo 'znaleziono '.$line2.' w '.$linia.', wiersz pliku nr '.$licznik;
  14. //tu podejmiesz jakąś akcję po znalezieniu i pętla kończy działanie
  15. break;
  16. }
  17. }
  18. fclose($uchwyt);
- pisane z palca, więc może nie działać. Zakładam, że jak w słowniku masz np. słowo CIUL a wiersz pliku zawiera "Pozdrawiam Was CIULE" to ma to znaleźć. Jeśli mają to być jakieś skomplikowane wyrażenia regularne etc. to trzeba pokombinować z takimi funkcjami:
http://pl2.php.net/manual/pl/function.preg-grep.php
Qwer
feof()+fgets() użyłem teraz, wcześniej użyłem też file() czyli wczytania do tablicy całego pliku i wtedy porównywania jednak, oba rozwiązania są kiepskie ponieważ plik ma jakieś 400000 linijek co należy pomnożyć przez ilość kombinacji dla każdej (ilość kanałów razy ilość wyrazów). Strasznie obciąża kompa i na koniec się wysypuje. Chyba że użyłeś czegoś co zapobiegnie takiemu obciążeniu, jeżeli tak i możesz to proszę opisz mniej więcej jak chciałeś to zrobić, z góry dzięki.

To co ma być znalezione także jest wrzucone do tablicy, robi to pierwsza pętla, łączy plik kanałów z plikiem słownika.

przykładowe wyrażenie do znalezienia po połączeniu tylko jednego kanału z tylko jednym wyrazem:
^\[.. ... ..:..:..\] PARTY \[.*\] .*kur.*
Pilsener
Jeżeli to ma być wyrażenie regularne to na pewno nie będzie szybkie, w swoim kodzie użyłem optymalnego przeszukiwania stringu do znalezienia w nim pierwszego wystąpienia szukanej frazy zamiast pregmatch, użyłem pętli foreach zamiast for, rtrim zamiast trim i zrezygnowałem z count, która nie wiem po co znalazła się w Twoim kodzie.

By działało szybciej proponuję porcjować to, co ma być wyszukiwane, zacząć od pliku z 1 szukanym wyrażeniem i sprawdzić jak działa i dopasować liczbę wyrażeń do możliwości serwera. Innej możliwości nie widzę.
Qwer
Dzięki za pomoc, mój skrypt już działa, błąd polegał na tym, że drugie wyrażenie regularne było źle sformułowane (drugi kanał) stąd się wysypywał, dalej jednak znacznie obciąża kompa, z czasem może i nad tym pomyślę rozpracowując to co podałeś i wykorzystując do swoich potrzeb, dzięki.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.