Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP]Wyrażenia regularne - złapanie między przecinkami z małym wyjątkiem
konrados
post 13.06.2015, 18:09:57
Post #1





Grupa: Zarejestrowani
Postów: 623
Pomógł: 79
Dołączył: 16.01.2008

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


Hej.

Powiedzmy, że mamy taki string:

  1. $string='
  2. blah<br>
  3. @include (\'file_to_load\')
  4. <br>
  5. @include (\'file_to_load\',\'param1\',\'param2\',\'param3\')
  6. ';


Chcę złapać (i ewentualnie zastąpić funkcją preg_replace_callback) wszystkie wystąpienia @include wraz z ich parametrami, robię więc:

  1.  
  2.  
  3. $string='
  4. blah<br>
  5. @include (\'file_to_load\')
  6. <br>
  7. @include (\'file_to_load\',\'param1\',\'param2\')
  8. ';
  9. $params=[];
  10. '~@include \((,?.*?)\)~',//łapię @include, nawiasy i wszystko między nimi
  11. function ($matches) {
  12. echo '---iteration---';
  13. $params=explode(',',$matches[1]);//rozdzielam parametry wg przecinka
  14. echo '<pre>';
  15. var_dump($params);
  16. echo '</pre>';
  17. return $matches[1];
  18. },
  19. $string
  20. );


No i działa OK, tzn. łapię to @include wraz z parametrami

Problem pojawia się, gdy w $stringu źródłowym, w samym parametrze pojawi się przecinek. Np:
  1. $string='
  2. blah<br>
  3. @include (\'file_to_load\')
  4. <br>
  5. @include (\'file_to_load\',\'param1,coś tam\',['elem'=>'też, przecinek']])
  6. ';


Tutaj w okolicach "param1" oraz czegoś co ma być arrayem są przecinki, chciałbym by były one elementem tego parametru, niestety oczywiście po użyciu funkcji "explode" ona widzi te przecinki i powstają bzdury.

Co mam zrobić, by przecinki będące w apostrofach były brane dosłownie, a nie były rozdzielnikiem parametrów?
Go to the top of the page
+Quote Post
kreatiff
post 13.06.2015, 21:24:33
Post #2





Grupa: Zarejestrowani
Postów: 324
Pomógł: 105
Dołączył: 7.08.2012

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


Trzeba zamiast explode użyć coś bardziej skomplikowanego. Można iść ponownie w wyrażenia regularne, np.:
  1. $a = '\'file_to_load\',\'param1,coś tam\',[\'elem\'=>\'też, przecinek\'],\'as\'';
  2. $b = preg_split('#(?<=(?:\'|\])),#', $a);
  3. echo'<pre>',var_dump($b),'</pre>';
Ale trzeba to posprawdzać na wszystkich mozliwych kombinacjach występujących przy @include.
Go to the top of the page
+Quote Post
konrados
post 13.06.2015, 22:26:31
Post #3





Grupa: Zarejestrowani
Postów: 623
Pomógł: 79
Dołączył: 16.01.2008

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


Dzięki, działa!

Nic a nic nie rozumiem z tego wyrażenia smile.gif

Muszę mocno wreszcie się za edukację w tym zakresie wziąć.

Jeśli to nie będzie skomplikowane, to jeszcze jedna drobnostka smile.gif Mając taki string:

  1. $a = '\'file_to_load\',\'param1,coś tam\',[\'elem\'=>\'też, przecinek\'],\'as\'';


To wyrażenie rozdziela też to co znajduje się pomiędzy nawiasami kwadratowymi [ oraz ] - a dałoby się by nie rozdzielało? Czyli by też zostawiło tak jak jest?

Myślałem, że po tym jak teraz poznałem funkcję preg_split to może dam radę sam, ale tak jak powiedziałem, to wyrażenie to dla mnie czarna magia...
Go to the top of the page
+Quote Post
kreatiff
post 13.06.2015, 23:55:32
Post #4





Grupa: Zarejestrowani
Postów: 324
Pomógł: 105
Dołączył: 7.08.2012

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


Ja otrzymuję taki wynik po zastosowaniu wyrażenia, które zaproponowałem:
  1. array(4) {
  2. [0]=>
  3. string(14) "'file_to_load'"
  4. [1]=>
  5. string(17) "'param1,coś tam'"
  6. [2]=>
  7. string(27) "['elem'=>'też, przecinek']"
  8. [3]=>
  9. string(4) "'as'"
  10. }:
Czyli to co w indeksie nr 2 ma być inne? Wyjaśnij i zobaczymy co da się zrobić.

Co do wyrażenia regularnego, to szuka ono przecinka, który jest poprzedzony albo apostrofem, albo zamknięciem nawiasu kwadratowego. I string jest cięty tylko w miejscach przecinków spełniających to założenie.

?<= - positive lookbehind, po tych symbolach wypisujemy znaki, które muszą poprzedzać dopasowany znak (ciąg)
(?: ... ) - nie łap tej grupy do wyniku, w sumie to jest zbędne, preg_split niczego "nie łapie", zapędziłem się, bo bardzo rzadko z tej funkcji korzystam, przeciwnie do preg_match, gdzie to z kolei już jest często stosowane (poniżej dałem uproszczone wyrażenie))
\'|\] - znaki, które muszą poprzedzać nasz przecinek, by ten był uwzględniony jako miejsce cięcia ciągu
, - szukaj przecinka (poprzedzonego tym co wyżej wyznaczone)

Wyrzucając to co zbędne, mamy takie wyrażenie:
  1. $b = preg_split('#(?<=\'|\]),#', $a);


Ten post edytował kreatiff 13.06.2015, 23:58:24
Go to the top of the page
+Quote Post
konrados
post 14.06.2015, 19:48:39
Post #5





Grupa: Zarejestrowani
Postów: 623
Pomógł: 79
Dołączył: 16.01.2008

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


Wow, dzięki za wyrażenie i wytłumaczenie!
Go to the top of the page
+Quote Post

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

 



RSS Wersja Lo-Fi Aktualny czas: 21.06.2025 - 08:30