Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [PHP]Wyszukiwanie w pliku logu
Qwer
post
Post #1





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 15.09.2009

Ostrzeżenie: (0%)
-----


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.

Ten post edytował Qwer 26.12.2009, 19:49:09
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 4)
Pilsener
post
Post #2





Grupa: Zarejestrowani
Postów: 1 590
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

Ostrzeżenie: (0%)
-----


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
Go to the top of the page
+Quote Post
Qwer
post
Post #3





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 15.09.2009

Ostrzeżenie: (0%)
-----


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.*

Ten post edytował Qwer 27.12.2009, 10:39:12
Go to the top of the page
+Quote Post
Pilsener
post
Post #4





Grupa: Zarejestrowani
Postów: 1 590
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

Ostrzeżenie: (0%)
-----


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ę.
Go to the top of the page
+Quote Post
Qwer
post
Post #5





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 15.09.2009

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 18.09.2025 - 23:36