2012-05-13 31 views
6
$pattern = "/\[(.*?)\]\((.*?)\)/i"; 
$replace = "<a href=\"$2\" rel=\"nofollow\">$1</a>"; 
$text = "blah blah [LINK1](http://example.com) blah [LINK2](http://sub.example.com/) blah blah ?"; 
echo preg_replace($pattern, $replace, $text); 

Các công trình trên nhưng nếu một không gian vô tình chèn vào giữa [] và() phá vỡ tất cả mọi thứ và cả hai liên kết được trộn vào một:Tại sao regex PHP của tôi phân tích cú pháp liên kết Markdown bị hỏng?

$text = "blah blah [LINK1] (http://example.com) blah [LINK2](http://sub.example.com/) blah blah ?"; 

Tôi có cảm giác nó là ngôi sao LAXY mà phá vỡ nó nhưng không biết cách khác để khớp các liên kết lặp lại.

+0

Đây có phải là một số loại Markdown phân tích cú pháp? Nếu vậy, tại sao bạn không sử dụng một cái đã tồn tại? – Gumbo

+0

Đó là. Tôi chỉ cần chức năng liên kết cơ bản mà không cần id và tiêu đề. – user1070125

Trả lời

7

Nếu tôi hiểu bạn đúng, tất cả các bạn cần làm thực sự cũng là phù hợp với bất kỳ số lượng khoảng trống giữa hai là tốt, ví dụ:

/\[([^]]*)\] *\(([^)]*)\)/i 

Giải thích:

\[    # Matches the opening square bracket (escaped) 
([^]]*)  # Captures any number of characters that aren't close square brackets 
\]    # Match close square bracket (escaped) 
*    # Match any number of spaces 
\(   # Match the opening bracket (escaped) 
([^)]*)  # Captures any number of characters that aren't close brackets 
\)    # Match the close bracket (escaped) 

Biện minh:

Tôi có lẽ nên biện minh rằng lý do tôi đã thay đổi .*? thành [^]]*

của bạn

Phiên bản thứ hai hiệu quả hơn vì nó không cần phải thực hiện một số lượng lớn backtracking mà .*? thực hiện. Ngoài ra, khi gặp phải [ mở, phiên bản .*? sẽ tiếp tục tìm kiếm cho đến khi tìm thấy kết quả khớp, thay vì thất bại nếu đó không phải là thẻ như chúng tôi muốn. Ví dụ, nếu chúng ta phù hợp với biểu hiện sử dụng .*? chống lại:

Sad face :[ blah [LINK1](http://sub.example.com/) blah 

nó sẽ phù hợp

[ blah [LINK1] 

http://sub.example.com/ 

Sử dụng cách tiếp cận [^]]* sẽ có nghĩa là đầu vào là lần xuất hiện một cách chính xác.

+0

Cái này có lỗi đánh máy nhưng tôi không thể sửa nó vì tôi không chắc nó hoạt động như thế nào. – user1070125

+0

Bạn nói đúng, tôi đã sửa lỗi đánh máy và thêm lời giải thích cho bạn – Jarmex

+0

Tôi cũng đã thêm lý do tại sao tôi đã thay đổi '. *?' Thành '[^]] *' – Jarmex

0

Hãy thử điều này:

$pattern = "/\[(.*?)\]\s?\((.*?)\)/i"; 

\s? thêm vào giữa \[(.*?)\]\((.*?)\)

+0

Điều đó bằng cách nào đó hoạt động chăm sóc một không gian duy nhất. Tôi nghĩ rằng nó sẽ tốt hơn đòi hỏi đánh dấu nghiêm ngặt và bỏ qua tất cả mọi thứ khác (đầu ra như nó được). – user1070125

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