2015-05-21 16 views
9

Ostatnio studiowałem (bardziej w praktyce, aby powiedzieć prawdę) regex i dostrzegam jego moc. To żądanie podjęte przeze mnie (link), mam świadomość "referencji zwrotnej". Myślę, że rozumiem, jak to działa, działa w JavaScript, podczas gdy w PHP nie.Odwołanie zwrotne nie działa w PHP

Na przykład mam ten ciąg:

[b]Text B[/b] 
[i]Text I[/i] 
[u]Text U[/u] 
[s]Text S[/s] 

i użyć następującego wyrażenia regularnego:

\[(b|i|u|s)\]\s*(.*?)\s*\[\/\1\] 

Testowanie to na regex101.com prac, taką samą dla JavaScriptu, ale nie działa w PHP.

Przykład preg_replace (nie działa):

echo preg_replace(
    "/\[(b|i|u|s)\]\s*(.*?)\s*\[\/\1\]/i", 
    "<$1>$2</$1>", 
    "[b]Text[/b]" 
); 

Chociaż w ten sposób działa:

echo preg_replace(
    "/\[(b|i|u|s)\]\s*(.*?)\s*\[\/(b|i|u|s)\]/i", 
    "<$1>$2</$1>", 
    "[b]Text[/b]" 
); 

Nie mogę zrozumieć, gdzie się mylę, dzięki wszystkim, którzy mi pomagają.

Odpowiedz

10

To dlatego, że używasz podwójne cudzysłowie, wewnątrz podwójnym cudzysłowie \1 jest odczytywany jako notacji ósemkowej o charakterze (na SOH znak kontrolny = start z pozycji), a nie jak zbiegłego 1.

więc dwa sposoby:

stosowanie pojedynczego cudzysłowie:

'/\[(b|i|u|s)\]\s*(.*?)\s*\[\/\1\]/i' 

lub ucieczki backslash uzyskanie dosłownego backslash (na łańcuchu, nie za wzór):

"/\[(b|i|u|s)\]\s*(.*?)\s*\[\/\\1\]/i" 

Tak na marginesie, można napisać swój wzorzec tak:

$pattern = '~\[([bius])]\s*(.*?)\s*\[/\1]~i'; 

// with oniguruma notation 
$pattern = '~\[([bius])]\s*(.*?)\s*\[/\g{1}]~i'; 

// oniguruma too but relative: 
// (the second group on the left from the current position) 
$pattern = '~\[([bius])]\s*(.*?)\s*\[/\g{-2}]~i'; 
+0

Dziękuję za odpowiedź, nie myślałem, że popełniłem błąd takiego. Jednak próbowałem użyć wzorca z ~ (który nie wiedział, aby powiedzieć prawdę), ale nie działa, czy to nie jest Ale to nie działa dla wszystkich, czy jestem w błędzie? [link] (https://regex101.com/r/gV7xR5/2) –

+0

Czy można jednak krótko wyjaśnić (jeśli nie zaburzenie) różnicę między '/' a '~'? –

+1

@MicheleLapolla: możesz wybrać ogranicznik wzoru, który chcesz (http://php.net/manual/en/regexp.reference.delimiters.php), aby uniknąć ucieczki od literalnych ukośników we wzorcu, '~' jest lepszym wyborem. Te trzy wzorce działają dobrze, możesz je sprawdzić tutaj: https://eval.in/368317 –