2009-03-29 36 views
13

Próbuję dopasować ciąg znaków, który może pojawić się na wielu liniach. Zaczyna się i kończy z określonym ciągiem:W tym nowe linie w PHP preg_replace function

{a}some string 
can be multiple lines 
{/a} 

mogę chwycić wszystko między {a} i {/a} z regex? Wydaje się, że. nie pasuje do nowych linii, ale próbowałem następujących elementów bez powodzenia:

$template = preg_replace($'/\{a\}([.\n]+)\{\/a\}/', 'X', $template, -1, $count); 
echo $count; // prints 0 

To pasuje. lub \ n kiedy są sami, ale nie razem!

Odpowiedz

31

Użyj s modifier:

$template = preg_replace($'/\{a\}([.\n]+)\{\/a\}/s', 'X', $template, -1, $count); 
//            ^
echo $count; 
+0

Wspaniale, wiedziałem, że będzie to coś prostszego! – DisgruntledGoat

+0

Po prostu stwierdziłem, że te informacje są na stronie PHP, mimo że nigdy nie znalazłem tego wcześniej, gdy szukałem ... http://www.php.net/manual/en/reference.pcre.pattern.modifiers .php – DisgruntledGoat

6

Myślę, że masz więcej problemów niż tylko kropka nie pasująca do nowych linii, ale pozwól mi zacząć od zalecenia formatowania. Możesz użyć prawie dowolnego znaku interpunkcyjnego jako ogranicznika regex, a nie tylko ukośnika ("/"). Jeśli użyjesz innej postaci, nie będziesz musiał uciec z ukośników w regex. Rozumiem, że "%" jest popularny wśród PHPers; która stałaby swoją argumentację Wzór:

'%\{a\}([.\n]+)\{/a\}%' 

Teraz powód, że regex nie działa jak ma się tak, ponieważ kropka traci swoje szczególne znaczenie, gdy pojawi się wewnątrz klasy znaków (nawiasy kwadratowe) - tak [.\n] po prostu pasuje do kropki lub linii. Czego szukali był (?:.|\n), ale bym zaleca dopasowanie powrotu karetki, a także wysuw:

'%\{a\}((?:.|[\r\n])+)\{/a\}%' 

To dlatego, że słowo „nowej linii” może odnosić się do stylu Unix „\ n”, Styl "\ r \ n" w stylu systemu Windows lub starszy styl Mac "\ r". Każda dana strona internetowa może zawierać dowolne z nich lub mieszankę dwóch lub więcej stylów; mieszanka "\ n" i "\ r \ n" jest bardzo powszechna. Ale z/sw trybie (znany również jako pojedynczej linii lub w trybie dotall), nie trzeba się martwić, że:

'%\{a\}(.+)\{/a\}%s' 

Istnieje jednak inny problem z oryginalnego regex, który jest wciąż obecny w tym jednym: + jest chciwy. Oznacza to, że jeśli w tekście występuje więcej niż jedna sekwencja {a}...{/a}, po pierwszym zastosowaniu wyrażenia regularnego dopasuje je wszystkie, od pierwszego {a} do ostatniego . Najprostszym sposobem, aby naprawić to, aby + ungreedy (aka „leniwy” lub „niechętnie”) poprzez dodanie znaku zapytania:

'%\{a\}(.+?)\{/a\}%s' 

Wreszcie, nie wiem, co zrobić z „$ "przed początkowym cytatem argumentu dotyczącego wzorca. Nie robię PHP, ale wygląda mi to na błąd składni. Jeśli ktoś mógłby mnie o tym poinformować, byłbym wdzięczny.

+0

Och, to musi być literówka - początkowo użyłem zmiennej i zastąpiłem ją ciągiem znaków dla tego przykładu. – DisgruntledGoat

+0

To było świetne wyjaśnienie. Pozdrawiam za to. – craignewkirk