2012-06-15 9 views
20

Tak z ciekawości, próbuję dowiedzieć się, która dokładnie jest właściwa droga ucieczki ukośnika do użytku w PHP wzorcu wyrażenia regularnego tak:Właściwy sposób na ucieczkę ukośnika odwrotnego [] w PHP regex?

TEST 01: (3 backslashe)

$pattern = "/^[\\\]{1,}$/"; 
$string = '\\'; 

// ----- RETURNS A MATCH ----- 

Test 02: (4 backslashe)

$pattern = "/^[\\\\]{1,}$/"; 
$string = '\\'; 

// ----- ALSO RETURNS A MATCH ----- 

według poniższych artykułów 4 przypuszczalnie w odpowiedni sposób, ale w kapelusz myli mnie, że oba testy zwróciły mecz. Jeśli obie mają rację, to 4 jest preferowanym sposobem?

zasoby:

Odpowiedz

4

Chodzi o to, że używasz klasy znaków [], więc to nie ma znaczenia, ile są literalne backslashe osadzone w nim, będzie traktowane jako pojedynczy odwrócony ukośnik.

np. następujące dwa wyrażenia regularne:

/[a]/ 
/[aa]/ 

są dla wszystkich zamiarów i celów identyczne, jak w przypadku silnika regex. Klasy postaci pobierają listę znaków i "zwijają" je, aby dopasować pojedynczy znak, zgodnie z liniami "dla bieżącej postaci, czy jest to jakikolwiek z znaków wymienionych wewnątrz []?". Jeśli podasz dwa odwrotne ukośniki w klasie, to będzie to "czy char to czarny kresk lub czy jest to ukośnik odwrotny?".

+0

W obu przypadkach silnik regex uważa to za pojedynczy ukośnik odwrotny? –

+3

'\ [\]' byłoby wyjściem z nawisu zamykającego. '[\\]' będzie odwrotnym ukośnikiem w klasie znaków. klasa pojedynczego znaku jest raczej bezcelowa, nie różni się niczym od zwykłego "\\\". –

35
// PHP 5.4.1 

// Either three or four \ can be used to match a '\'. 
echo preg_match('/\\\/', '\\');  // 1 
echo preg_match('/\\\\/', '\\');  // 1 

// Match two backslashes `\\`. 
echo preg_match('/\\\\\\/', '\\\\'); // Warning: No ending delimiter '/' found 
echo preg_match('/\\\\\\\/', '\\\\'); // 1 
echo preg_match('/\\\\\\\\/', '\\\\'); // 1 

// Match one backslash using a character class. 
echo preg_match('/[\\]/', '\\');  // 0 
echo preg_match('/[\\\]/', '\\');  // 1 
echo preg_match('/[\\\\]/', '\\');  // 1 

Przy użyciu trzech backslashy dopasować '\' WZÓR interpretowane jako dopasować '\' następnie przez 's'.

echo preg_match('/\\\\s/', '\\ '); // 0 
echo preg_match('/\\\\s/', '\\s'); // 1 

Przy zastosowaniu czterech backslashy dopasować '\' wzór poniżej jest interpretowany jako dopasować '\' następnie znak spacji.

echo preg_match('/\\\\\s/', '\\ '); // 1 
echo preg_match('/\\\\\s/', '\\s'); // 0 

To samo dotyczy wnętrza klasy postaci.

echo preg_match('/[\\\\s]/', ' '); // 0 
echo preg_match('/[\\\\\s]/', ' '); // 1 

Żaden z powyższych wyników wpływa załączając sznurki w podwójne zamiast pojedynczych cudzysłowach.

Wnioski:
czy wewnątrz lub poza nawiasami klasy postaci, dosłowny odwrotny ukośnik można dopasować za pomocą zaledwie trzech backslashy '\\\' chyba że następny znak w strukturze jest również odwrotnym ukośnikiem, w którym to przypadku dosłowny odwrotny ukośnik musi być dopasowany za pomocą czterech ukośników odwrotnych.

Zalecenie:
Zawsze użyć czterech backslashe '\\\\' w deseń regex, gdy stara się dopasować odwrotny ukośnik.

Escape sequences.

+0

Kiedy próbuję [\\], zawsze otrzymuję komunikat: preg_match(): Kompilacja nieudana: brakujące zakończenie] dla klasy znaków przy przesunięciu 3 – CMCDragonkai

+0

Powinno być oznaczone jako odpowiedź @Mahmoud Tahan – Lsakurifaisu

0

Studiowałem to lata temu. Dzieje się tak dlatego, że pierwszy ukośnik odwraca się od drugiego i razem tworzą "prawdziwy znak baclkslasha" we wzorze, a ten prawdziwy ucieka z trzeciego. Więc magicznie działa 3 backslashes.

Jednak normalną sugestią jest użycie 4 ukośników odwrotnych zamiast niejednoznacznych 3 ukośników odwrotnych.

Jeśli się mylę, proszę mnie poprawić.

+1

-1: 'i to prawda ucieka trzeci "Nie". Wykonuje się tylko jedno przejście. Trzeci ukośnik odwrotny "ucieka" przed ']' (co po prostu powoduje ']' na własną rękę). –

+0

@ Lightness: Więc dlaczego "/ (\\\ r) \ 1 + /" będzie pasować powtórzone "\" i "r" (mam na myśli 2 prawdziwe znaki)? Możesz wytłumaczyć? –

+0

'\ r' jest sekwencją ucieczkową; '\]' nie jest. –

9

Aby uniknąć tego rodzaju kodu niejasnej można użyć \ x5c like this :)

echo preg_replace('/\x5c\w+\.php$/i', '<b>${0}</b>', __FILE__); 
+0

Chcę tylko podziękować za to. Uciekanie postaci ucieczki, takich jak '\ n', już jest problemem, ale zrobienie tego w trybie regex z lookbehind jest wyzwaniem. –

0

Można również użyć następujących

$regexp = <<<EOR 
schemaLocation\s*=\s*["'](.*?)["'] 
EOR; 
preg_match_all("/".$regexp."/", $xml, $matches); 
print_r($matches); 

słowa kluczowe: dochere, nowdoc

Powiązane problemy