Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Problem z preg_match_all
Forum PHP.pl > Forum > Przedszkole
Ulysess
dobry wieczór , mam oto taki skrypt:
  1. <?php
  2.  
  3. $page = file_get_contents("old/page.txt");
  4.  
  5. echo '<table>
  6. <tr>
  7. <td></td>
  8. <td></td>
  9. <td></td>
  10. <td></td>
  11. <td></td>
  12. <td></td>
  13. <td></td>
  14. </tr>';
  15.  
  16. preg_match_all('#<a href="#" onClick="window.open(\'gildia_informacje.php?id=(.*)\',\'Informacje\',\'width=550,height=810,top=0,left=0,scrollbars=yes,\');" style="font-size: 13px; color: #BFAC2B; font-weight: bold;">(.*)</a></b></td>
  17. <td background="images/tabelka_metalowa/prawa.jpg" width="11" align="center" ></td>
  18. </tr>
  19. <tr>
  20. <td></td>
  21. <td width="120" align="center" valign="top"><img border="1" src="(.*)"><br>(.*)</td>
  22. <td valign="top" height="40">
  23. <b style="font-size: 18px; color: darkred;">(.*)</b> -
  24. <b style="font-size: 12px; color: green;">(.*)</b>
  25. <div align="left">Szacunek: <b>(.*)</b><br>Liczba członków: <b>(.*)</b>#', $page, $matches);
  26.  
  27. $length = count($matches[0]);
  28. echo $length;
  29. for ( $i = 0; $i < $length; $i++ )
  30. {
  31. echo '<tr>';
  32. echo '<td>'.$matches[0][$i].'</td>';
  33. echo '<td>'.$matches[1][$i].'</td>';
  34. echo '<td>'.$matches[2][$i].'</td>';
  35. echo '<td>'.$matches[3][$i].'</td>';
  36. echo '<td>'.$matches[4][$i].'</td>';
  37. echo '<td>'.$matches[5][$i].'</td>';
  38. echo '<td>'.$matches[6][$i].'</td>';
  39. echo '</tr>';
  40. }
  41.  
  42. echo '</table>';
  43.  
  44. ?>


jego zadaniem jest otworzyć dokument page.txt i wyciągnąć interesujące mnie dane które podałem w modelu. Problem polega na tym że wywala "
Warning: preg_match_all() [function.preg-match-all]: Unknown modifier '"' in E:\VertrigoServ\www\skrypt.php on line 25"

nie mam zielonego pojęcia o co mu chodzi..
Valdi_B
W wyrażeniu regułowym (1-szym argumencie preg_match) jako ograniczniki użyłeś znaku "#".
Kolizja polega na tym, że znak "#" masz w środku tego wyrażenia.

Metoda 1. Zmień ograniczniki na jakieś inne.
Metoda 2. Poprzedź ten "środkowy #" znakiem "\".

Co do met. 2 nie jestem do końca pewny, ale sprawdź i odpisz.

Edit:
W treści wzorca masz w 8 miejscach sekwencje "(.*)" - jak widać - subwzorce przechwytywane.
Zwróć jednak uwagę, że masz tam także nawiasy wokół argumentów funkcji window.open.
Dla preg_match te nawiasy TAKŻE będą ogranicznikami subwzorca, a to chyba nie to, czego chcesz.
Być może oba te nawiasy też musisz poprzedzić znakiem "\".
zegarek84
metoda druga także pozwoli ominąć błąd... jednak ZONK'a wciąż będzie miał przez pójście na łatwiznę bez zrozumienia wyrażeń regularnych i przekopiowanie kodu HTML na żywca do ciągu... dla przykładu fragment z brzegu: gildia_informacje.php?id - co może oznaczać także "gildia_informacjeFphid" lub "gildia_informacje.phpid" ale za czorta nie dopasuje się do "gildia_informacje.php?id" - jakie jest znaczenie kropki w wyrażeniach regularnych?? - dowolny jeden znak - no prawie dowolny - nie ma w nim definicji bodajże nowej linii i kilku innych - znaczenie znaku zapytania znaczy tyle co zapis {0,1} -> czyli możliwe wystąpienie 0 lub jeden poprzedzający znak - dalej nie chce mi się komentować... a do parsowania dokumentów HTML lepiej skozystać z DOM lub wpisać w google PHPQuery - jest to nakładka na DOM pozwalająca na korzystanie z selektorów jak w jQuery zwracająca elementy DOM - po więcej odsyłam do manuala php czy to o wyrażenia regularne czy o wspomniany DOM...

a propo wyrażeń regularnych to każdy ze znaków specjalnych trzeba poprzedzić znakiem "\"
Fifi209
Najprościej preg_quote

Cytat(zegarek84 @ 5.03.2011, 21:31:54 ) *
jakie jest znaczenie kropki w wyrażeniach regularnych?? - dowolny jeden znak - no prawie dowolny - nie ma w nim definicji bodajże nowej linii i kilku innych -

Zależnie od Flag o czym mówi manual:
Cytat
If this modifier is set, a dot metacharacter in the pattern matches all characters, including newlines. Without it, newlines are excluded. This modifier is equivalent to Perl's /s modifier. A negative class such as [^a] always matches a newline character, independent of the setting of this modifier.

http://pl2.php.net/manual/pl/reference.pcr...n.modifiers.php
Ulysess
próbuje w sposób następujący:

  1. <?php
  2.  
  3. $page = file_get_contents("old/page.txt");
  4.  
  5. preg_match_all('~<table width="95%" cellpadding="4" cellspacing="0" border="0" align="center">
  6. <tr>
  7. <td background="images/tabelka_metalowa/lewa.jpg" width="11" align="center" ></td>
  8. <td class="tlo-g" colspan="2" align="center"><b><a href="#" onClick="window.open\(\'gildia_informacje.php?id=(.*)\',\'Informacje\',\'width=550,height=810,top=0,left=0,scrollbars=yes,\'\);" style="font-size: 13px; color: #BFAC2B; font-weight: bold;">(.*)</a></b></td>
  9. <td background="images/tabelka_metalowa/prawa.jpg" width="11" align="center" ></td>
  10. </tr>
  11. <tr>
  12. <td></td>
  13. <td width="120" align="center" valign="top"><img border="1" src="obrazkigildii/(.*)"><br>(.*)</td>
  14. <td valign="top" height="40">
  15. <b style="font-size: 18px; color: darkred;">(.*)</b> -
  16. <b style="font-size: 12px; color: green;">(.*)</b>
  17.  
  18. <div align="left">Szacunek: <b>(.*)</b><br>Liczba członków: <b>(.*)</b><br><b>.*</b><br>Wymagany poziom: <b>.*</b></div><b>Regulamin:</b><br>.*</td>
  19. <td></td>
  20. </tr>
  21. <tr>
  22. <td background="images/tabelka_drewniana/lewa.jpg" align="center"></td>
  23. <td class="tlo-z" align="center">-</td>
  24. <td class="tlo-z"></td>
  25.  
  26. <td background="images/tabelka_drewniana/prawa.jpg" width="11" align="center" ></td>
  27. </tr>
  28. </table>~', $page, $matches);
  29.  
  30.  
  31. print_r($matches);
  32.  
  33. $suma = count($matches);
  34.  
  35. print_r($suma);
  36.  
  37. echo '<table>
  38. <tr>
  39. <td></td>
  40. <td></td>
  41. <td></td>
  42. <td></td>
  43. <td></td>
  44. <td></td>
  45. <td></td>
  46. </tr>';
  47.  
  48. for ( $i = 0; $i < $suma; $i++ )
  49. {
  50. echo '<tr>';
  51. echo '<td>'.$matches[0][$i].'</td>';
  52. echo '<td>'.$matches[1][$i].'</td>';
  53. echo '<td>'.$matches[2][$i].'</td>';
  54. echo '<td>'.$matches[3][$i].'</td>';
  55. echo '<td>'.$matches[4][$i].'</td>';
  56. echo '<td>'.$matches[5][$i].'</td>';
  57. echo '<td>'.$matches[6][$i].'</td>';
  58. echo '</tr>';
  59. }
  60.  
  61. echo '</table>';
  62.  
  63. ?>


zmienna matches zawiera Array ( [0] => Array ( ) [1] => Array ( ) [2] => Array ( ) [3] => Array ( ) [4] => Array ( ) [5] => Array ( ) [6] => Array ( ) [7] => Array ( ) [8] => Array ( ) ) 9

a nie o to przecież chodziło ...
Valdi_B
Fifi209 dobrze poradził, abyś użył funkcji preg_quote, która poprzedzi znakiem "\" każdy znak specjalny w wyrażeniach regułowych.
Skoro jednak nie chcesz tak zrobić, to przynajmniej postaw "\" przed "?" (który też ma specjalne znaczenie w wyrażeniach regułowych).

Edit:
Jak spowodować, aby wyrażenie regułowe nie było tak długie:
Popatrz na taki przykład:

$wyr = '\?id=(.*?)\',(?:.*?) bold;">(.*?)</a>';

Jest to wyrażenie regułowe, w którym:
1. Najpierw szukasz tekstu "?id=" (zwróć uwagę, że znak "?" trzeba poprzedzić znakiem "\").
2. Dalej -wzorzec przechwytujący nr 1 - "(.*?)"
Dodałem tu "?" aby wyszukiwanie było w wersji "skąpej" (ungreedy).
3. Potem (za szukanym tekstem nr 1) ma być apostrof i przecinek.
4. Kolejny fragment - (?:.*?) - to subwzorzec nieprzechwytujący (?:).
"skonsumuje" tekst przed tym co dalej, ale nie zwróci do wyniku.
5. Dalej mamy tekst poprzedzający 2-gi tekst do przechwycenia - ' bold;">'.
6. Wzorzec przechwytujący nr 2 - "(.*?)" (też w wersji "ungreedy").
7. Kończymy tekstem, który ma wystąpić po nim - "</a>".

To co powyżej przechwytuje 2 pierwsze subwzorce.
Dokończ tę konstrukcję i wstaw jako 1-szy argument do preg_match_all.
Ulysess
to co napisałeś jest dla mnie makabrą i nic z tego nie rozumiem..
probowałem z "\" przed ? niestety nie działa - dalej zwraca tablice z wartościa 1-9... próbowałem jeszcze inaczej wstawiając w miejsce kodu JS po prostu (.*) też zwraca tablice taką jak wcześniej tylko większą o +1 . czy aby problem nie jest w czym innym questionmark.gif..
Valdi_B
Sprawdź to co radziłem:
Zamiast Twojego wywołania preg_match_all(...) zrób:

$wyr = '\?id=(.*?)\',(?:.*?) bold;">(.*?)</a>';
preg_match_all($wyr, $page, $matches);

print_r(...) powinno wydrukować pierwsze 2 subwzorce
- po '?id=',
- po 'bold;">'

A idea tego rozwiązania jest taka:

Masz tekst typu:
aaaaaaaa xxx yyy zzz aaaaaaaaaaaaaaaaa
W tekście tym:
1. Chcesz przechwycić (nieznany Ci) tekst "yyy".
2. Przed nim występuje tekst (znany) "xxx ".
3. Po nim występuje tekst (też znany) " zzz".

Wyrażenie regułowe do preg_match musi mieć postać:
xxx (.*?) yyy

Jeżeli po tym fragmencie jest inny podobny fragment do przechwycenia, to we wzorcu musisz umieścić kolejny subwzorzec nieprzechwytujący - (?:.*?).
"Skonsumuje" on tekst przed następnym "znanym" tekstem.
Ciąg dalszy wzorca to powtórzenie tego co poprzednio:
uuu (.*?) vvv
(tym razem - jakieś inne teksty przed i po tym, co chcesz przechwycić).

A tak w ogóle: poczytaj sobie o wyrażeniach regułowych:
http://pl.php.net/manual/pl/reference.pcre...tern.syntax.php
Może wtedy mój opis nie będzie taki "makabryczny".
Po prostu używam pojęć tam zawartych (powinieneś je poznać).
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.