Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]preg_replace- zamiana spacji
Forum PHP.pl > Forum > Przedszkole
Kloc
Chcę zamienić wszystkie spacje pomiędzy znakiem > i < na !. Jak to zapisać za pomocą wyrażenia regularnego?

  1. preg_replace('#(.>.)\s(.<.)#si', '!', $string);


Ten zapis nic mi nie zmienia.
Turson
  1. preg_replace('#\>(\s*)\<#si', '!', $string);
SmokAnalog
Turson, przecież to jest bez sensu. Twoje wyrażenie zamieni te spacje tylko wtedy, kiedy w znaczniku nie ma nic innego. A po drugie, po co stawiasz backslash przed < i >?

Nie jestem pewien czy da się to zrobić w jednym wyrażeniu, ja bym to zrobił np. tak:
  1. '#>([^<]*)</#',
  2. function($matches) {
  3. return '>' . str_replace(' ', '!', $matches[1]) . '</';
  4. },
  5. $string
  6. );
by_ikar
Tak jak napisał smok, wielu ludzi zapomina że coś może się znajdować pomiędzy naszymi szukanymi, dlatego ich wyrażenia nie działają. Kolejna sprawa, to nie jestem do końca pewien czy nie dało by się tego zrobić w jednym wyrażeniu z jakimiś instrukcjami warunkowymi, tylko czy to ma sens jak można to załatwić callbackiem od ręki, tak jak to pokazał @Smok.
SmokAnalog
Właśnie coś mi się wydaje, że można jednym wyrażeniem, ale nie znam wszystkich meandrów wyrażeń regularnych smile.gif
Kloc
Dokładniej chcę zrobić aby wszystkie spacje w nowej linii, aż do pierwszego jakiegoś znaku zastąpić !.
Przejście do nowej linii wykonane jest za pomocą <br />, czyli wyrażenie musi zastąpić \s od <br /> aż do . niebędącego spacją.
Łatwo powiedzieć trudniej zapisać smile.gif. Np.

Tekst wejściowy:
Kod
jakis tekst cos tam cos tam<br />
   la la la la la, tu są 3 spacje
nastepna linia
     i kolejna linia, tu jest 5 spacji


Tekst wyjściowy:
Kod
jakis tekst cos tam cos tam<br />
***la la la la la, tu są 3 spacje
nastepna linia
*****i kolejna linia, tu jest 5 spacji


! zamieniłem na *, bo zamienia je na emotki.

Trochę pokombinowałem, pomyślałem i wymyśliłem takie coś. Dałe modyfikator m- wielolinijkowość.

  1. preg_replace('#^\s+#m', '!', $string);


I to rozwiązanie działa w 50%, ponieważ zamienia mi wszystkie spacje zawszy na 1 wykrzyknik. A chcę aby każde spację zamieniało na osobne wykrzykniki, tak jak w przykładach.

Chcę uzyskać taki efekt jak tu na forum. Zbadajcie sobie przykład poniżej.
Prawy klawisz myszy > zbadaj element > div class = codemain

Kod
jakis tekst cos tam cos tam<br />
   la la la la la, tu są 3 spacje
nastepna linia
     i kolejna linia, tu jest 5 spacji


Każda spacja w nowej linii, aż do jakiegoś znaku jest zamieniana na twardą spację, reszta jest normalna. Chcę zrobić tak samo, ale nie wiem jak, a koła na nowo nie ma co wymyślać.
Wie ktoś jak to zrobić?
by_ikar
Cytat(SmokAnalog @ 26.07.2014, 17:23:15 ) *
Właśnie coś mi się wydaje, że można jednym wyrażeniem, ale nie znam wszystkich meandrów wyrażeń regularnych smile.gif


Da się na pewno, ale skomplikowanie i poświęcony czas na przetestowanie tego, jest nie warty, zwłaszcza że autor w końcu napisał o co mu chodziło, i nie chodziło więc to zmienia całe "nasze" założenie.

Twój problem da się rozwiązać, ale wciąż z użyciem callback dlatego że o ile jeden znak jak będziesz szukać i podmieniać, to podmieni ci wszystkie, ale jak chcesz do tego dodać jakąś "kotwice", czyli w konkretnym miejscu, no to wtedy już złapie albo jeden znak, albo wszystkie. Więc całość mogłaby wyglądać tak:

  1. $str = 'jakis tekst cos tam cos tam<br />
  2. la la la la la, tu sa 3 spacje
  3. nastepna linia
  4. i kolejna linia, tu jest 5 spacji';
  5.  
  6. $callback = function($matches) {
  7. return str_replace(' ', '!', $matches[1]);
  8. };
  9.  
  10. $res = preg_replace_callback('#(?<=\n)(\s+)#', $callback, $str);
  11.  
  12. var_dump($res);


Możesz sprawdzić jak to działa tutaj: http://writecodeonline.com/php/ tyle że ja nie jestem pewien czy dokładnie o to tobie chodziło. Najlepiej jakbyś pokazał dokładny przykład, łącznie z wszystkimi spacjami, przejściem do nowej linii etc.

PS. jest to tak zwane pozytywne przewidywanie wsteczne (positive lookbehind).
SmokAnalog
Cytat(by_ikar @ 28.07.2014, 00:53:00 ) *
  1. $res = preg_replace_callback('#(?<=\n)(\s+)#', $callback, $str);

Dokładnie to samo można dużo prościej zrobić:
  1. $res = preg_replace_callback('#^ +#m', $callback, $str);


I wtedy w callbacku użyć $matches[0] zamiast $matches[1].
Kloc
Dokładnie o ten efekt mi chodziło biggrin.gif Dzięki!.
Jakby ktoś mógł jeszcze mi to przetłumaczyć na polski, bo nie do końca rozumiem co się dzieje tutaj

  1. $callback = function($matches) {
  2. return str_replace(' ', '!', $matches[0]);
  3. };


A dokładniej o co chodzi z tą tablicą $matches[0]?
by_ikar
W tym wypadku zmienna $callback jest funkcją anonimową (którą możesz używać jak funkcję: http://php.net/manual/en/functions.anonymous.php ), ale zapisaną do zmiennej i do tej funkcji przekazywane są "wystąpienia", a w dalszej części twój kod wewnątrz tej funkcji obrabia te wystąpienia. Z racji tego że wyrażenia można grupować (lub nie) powstaje wiele elementów tablicy $matches. Np @Smok nie użył grupowania, dlatego w jego przypadku musisz się odwołać do pierwszego elementu (czyli ciąg do którego zostało dopasowane całe wyrażenie), w moim przypadku, użyłem grupowania (nawiasy grupują) i z racji że jest to pierwsza grupa, musisz odwołać się do $matches[1] (bo już wiesz że $matches[0] odnosi się do całego ciągu do którego zostało dopasowane wyrażenie). No a jakby to była druga grupa, o wtedy musiałbyś użyć $matches[2] i tak dalej. W moim przypadku jakbyś użył $matches[0] to dopasowało by ci do nowej linii i spacji występujących po niej, zamiast tylko do spacji. Dlatego się grupuje wyrażenia, aby mieć dostęp do tego co nas interesuje, zamiast całego ciągu.

No i kolejną sprawą jest to że ja przypisałem swoją funkcję anonimową do zmiennej, bo dla mnie jest tak czytelniej, a @smok od razu przekazał tą funkcję jako argument preg_replace_callback.
Kloc
Jeszcze raz wielkie dzięki, to mi rozjaśniło wszystkie wątpliwości, dzięki czemu jestem o kroczek dalej na phpowej drodze smile.gif
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.