2010-12-08 42 views
12

Tôi đang cố gắng tìm một giải pháp đáng tin cậy để trích xuất url từ chuỗi ký tự. Tôi có một trang web nơi người dùng trả lời câu hỏi và trong hộp nguồn, nơi họ nhập nguồn thông tin của họ, tôi cho phép họ nhập url. Tôi muốn trích xuất url đó và biến nó thành siêu liên kết. Tương tự như cách Yahoo Answers làm điều đó.Trích xuất URL từ chuỗi

Có ai biết giải pháp đáng tin cậy có thể thực hiện việc này không?

Tất cả các giải pháp mà tôi đã tìm được đều có tác dụng đối với một số URL nhưng không phải cho những người khác.

Cảm ơn

Trả lời

22

John Gruber có spent a fair amount of time hoàn thiện cơ chế "một regex để cai trị tất cả" để phát hiện liên kết. Sử dụng preg_replace() như đã đề cập trong câu trả lời khác, bằng cách sử dụng regex sau nên là một trong những chính xác nhất, nếu không phải là chính xác nhất, phương pháp để phát hiện một liên kết:

(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])) 

Nếu bạn chỉ muốn để phù hợp với HTTP/HTTPS:

(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])) 
+0

Chính xác những gì tôi đang tìm kiếm Cảm ơn bạn –

+4

Đối với bất kỳ ai muốn tất cả các mẫu con được chuyển đổi thành không chụp, và dấu gạch chéo về phía trước đã thoát: \ b (?: (?: [az] [\ w -] +: (?: \/{1,3} | [a-z0-9%]) | www \ d {0,3 } [.] | [a-z0-9. \ -] + [.] [az] {2,4} \ /) (?: [^ \ s() <>] + | \ ((?: [^\ s() <>] + | (?: \ ([^ \ s() <>] + \))) * \)) + (?: \ ((?: [^ \ s() <> ] + | (?: \ ([^ \ s() <>] + \))) * \) | [^ \ s'!() \ [\] {} ;: '"., <>?« »“ ”''])) –

+0

TLD có thể có nhiều hơn 4 ký tự, xem: http://www.iana.org/domains/root/db – Toto

0

Yahoo! Câu trả lời thực hiện công việc nhận dạng liên kết khá tốt khi liên kết được viết đúng và tách biệt với văn bản khác, nhưng không tách biệt dấu chấm câu. Ví dụ: The links are http://example.com/somepage.php , http://example.com/somepage2.php , and http://example.com/somepage3.php . sẽ bao gồm dấu phẩy trên hai dấu đầu tiên và dấu chấm thứ ba.

Nhưng nếu đó là chấp nhận được, sau đó mô hình như thế này nên làm điều đó:

\<http:[^ ]+\> 

Dường như phân tích cú pháp stackoverflow là tốt hơn. Là mã nguồn mở?

+0

thông minh hơn, nhưng vẫn chưa hoàn hảo. nhớ những thứ như ssh + svn. – DampeS8N

3
$string = preg_replace('/https?:\/\/[^\s"<>]+/', '<a href="$0" target="_blank">$0</a>', $string); 

Chỉ khớp với http/https, nhưng đó thực sự là giao thức duy nhất bạn muốn chuyển thành liên kết. Nếu bạn muốn người khác, bạn có thể thay đổi nó như thế này:

$string = preg_replace('/(https?|ssh|ftp):\/\/[^\s"]+/', '<a href="$0" target="_blank">$0</a>', $string); 
+1

Bạn cũng có thể muốn loại trừ '<' hoặc áp dụng 'htmlspecialchars' trên chuỗi phù hợp để tránh việc tiêm mã. – Gumbo

+0

Tốt, nhưng nếu bạn nhìn vào biểu thức, nó cho phép bất cứ điều gì ngoài khoảng trắng và '' '. Tôi tin rằng loại bỏ bất kỳ sự tiêm HTML nào. – Jonah

+1

Bron: Không, bạn đang sử dụng giá trị khớp không chỉ như giá trị thuộc tính mà còn – Gumbo

-1

Mã này đã hoạt động đối với tôi.

function makeLink($string){ 

/*** make sure there is an http:// on all URLs ***/ 
$string = preg_replace("/([^\w\/])(www\.[a-z0-9\-]+\.[a-z0-9\-]+)/i", "$1http://$2",$string); 
/*** make all URLs links ***/ 
$string = preg_replace("/([\w]+:\/\/[\w-?&;#~=\.\/\@]+[\w\/])/i","<a target=\"_blank\" href=\"$1\">$1</a>",$string); 
/*** make all emails hot links ***/ 
$string = preg_replace("/([\w-?&;#~=\.\/]+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?))/i","<a href=\"mailto:$1\">$1</a>",$string); 

return $string; 
} 
+1

Tại sao bạn giới hạn tld thành 3 ký tự? Hãy xem tại: http://www.iana.org/domains/root/db – Toto

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