2012-06-15 61 views
20

Chỉ vì tò mò, tôi đang cố gắng để tìm ra chính xác là đúng cách để thoát khỏi một dấu gạch chéo để sử dụng trong một mẫu biểu thức chính quy PHP như sau:Cách tốt nhất để thoát khỏi dấu gạch chéo ngược [] trong PHP regex?

NGHIỆM 01: (3 gạch chéo ngược)

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

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

NGHIỆM 02: (4 backslashes)

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

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

Theo bài viết dưới đây, 4 được cho là đúng cách nhưng w hat confuses tôi là cả hai bài kiểm tra trả về một trận đấu. Nếu cả hai đều đúng, thì đó là 4 cách ưu tiên?

NGUỒN:

Trả lời

4

Có điều là, bạn đang sử dụng một lớp nhân vật, [], vì vậy nó không quan trọng bao nhiêu backslashes đen là được nhúng vào trong nó, nó sẽ được coi là một dấu gạch chéo ngược duy nhất.

ví dụ: hai regex sau đây:

/[a]/ 
/[aa]/ 

dành cho tất cả ý định và mục đích giống hệt như động cơ regex. Lớp nhân vật lấy danh sách các ký tự và "thu gọn" chúng xuống để khớp với một ký tự đơn, dọc theo dòng "cho ký tự hiện tại đang được xem xét, có phải bất kỳ ký tự nào được liệt kê bên trong [] không?". Nếu bạn liệt kê hai dấu gạch chéo ngược trong lớp, sau đó nó sẽ là "là char một dấu gạch chéo ngược hoặc là một dấu gạch chéo ngược?".

+0

Vì vậy, trong cả hai trường hợp, công cụ regex coi đó là một dấu gạch chéo ngược duy nhất? –

+3

'\ [\]' sẽ là lối thoát của khung đóng. '[\\]' sẽ là dấu gạch chéo ngược trong một lớp ký tự. một lớp char đơn giản là vô nghĩa, nó sẽ không khác gì so với việc chỉ có một '\\\ 'trần. –

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 

Khi sử dụng ba dấu xồ nguợc để phù hợp với một '\' mô hình dưới đây được hiểu như là phù hợp với một '\' tiếp theo là một 's'.

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

Khi sử dụng bốn backslashes để phù hợp với một '\' mô hình dưới đây được hiểu như là phù hợp với một '\' theo sau là một nhân vật không gian.

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

Điều tương tự cũng áp dụng nếu bên trong một lớp nhân vật.

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

Không có kết quả nào ở trên bị ảnh hưởng bởi việc kèm theo chuỗi gấp đôi thay vì dấu nháy đơn.

Kết luận:
Cho dù bên trong hay bên ngoài một lớp nhân vật trong ngoặc vuông, một dấu chéo ngược nghĩa đen có thể được xuất hiện chỉ sử dụng ba dấu xồ nguợc '\\\' trừ khi nhân vật tiếp theo trong mô hình cũng được backslashed, trong trường hợp này xuyệc ngược đen phải phù hợp bằng bốn dấu gạch chéo ngược.

Khuyến nghị:
Luôn luôn sử dụng bốn backslashes '\\\\' trong một mô hình regex khi tìm kiếm để phù hợp với một dấu gạch chéo.

Escape sequences.

+0

Khi tôi thử [\\], tôi luôn nhận được Thông báo: preg_match(): Biên soạn không thành công: thiếu kết thúc] đối với lớp ký tự bù trừ 3 – CMCDragonkai

+0

Phải được đánh dấu là câu trả lời @Mahmoud Tahan – Lsakurifaisu

0

Tôi đã nghiên cứu cách đây vài năm. Đó là bởi vì dấu gạch chéo ngược thứ nhất thoát khỏi dấu gạch chéo thứ 2 và chúng cùng nhau tạo thành một ký tự 'baclkslash' thực sự trong mẫu và cái này đúng là thoát khỏi ký tự thứ 3. Vì vậy, nó kỳ diệu làm cho 3 dấu gạch chéo ngược hoạt động.

Tuy nhiên, đề xuất thông thường là sử dụng 4 dấu gạch chéo ngược thay vì 3 dấu gạch chéo ngược không rõ ràng.

Nếu tôi sai về bất cứ điều gì, vui lòng sửa tôi.

+1

-1: ' người thứ 3 "Không. Chỉ thực hiện một lần. Dấu gạch chéo ngược thứ ba "thoát" là ']' (chỉ kết quả trong ']' riêng của nó). –

+0

@ Nhẹ nhàng: Vậy tại sao '/ (\\\ r) \ 1 + /' sẽ khớp lặp lại '\' và 'r' (2 ký tự đúng, ý tôi là)? Bạn có thể giải thích? –

+0

'\ r' là một chuỗi thoát; '\]' thì không. –

9

Để tránh loại mã này không rõ ràng, bạn có thể sử dụng \ x5c Như thế này :)

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

Tôi chỉ muốn nói lời cảm ơn rất lớn vì điều này. Thoát các ký tự thoát như '\ n' là một nỗi đau, nhưng làm nó trong regex với lookbehind là một thách thức. –

0

Bạn cũng có thể sử dụng

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

từ khóa sau: dochere, nowdoc

Các vấn đề liên quan