2009-03-10 26 views
7

Tôi có vùng văn bản wysiwyg trong một ứng dụng web Java. Người dùng có thể nhập văn bản và tạo kiểu hoặc dán văn bản đã định dạng HTML.Liên kết văn bản với các cụm từ thông dụng trong Java

Điều tôi đang cố gắng thực hiện là liên kết văn bản. Điều này có nghĩa là chuyển đổi tất cả các URL có thể có trong văn bản thành "đối tác hoạt động" của họ, tức là thêm < a href = "..."> ... </a>.

Giải pháp này làm việc khi tất cả tôi có là văn bản đơn giản:

String r = "http(s)?://([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&amp;\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?"; 
Pattern pattern = Pattern.compile(r, Pattern.DOTALL | Pattern.UNIX_LINES | Pattern.CASE_INSENSITIVE); 
Matcher matcher = pattern.matcher(comment); 
comment = matcher.replaceAll("<a href=\"$0\">$0</a>"); // group 0 is the whole expression 

Nhưng vấn đề là khi có một số văn bản đã được định dạng, nghĩa là nó đã có < a href =". .. "> ... </a> thẻ.

Vì vậy, tôi đang tìm một cách nào đó để mô hình không phù hợp bất cứ khi nào nó tìm thấy văn bản giữa hai thẻ HTML (< a>). Tôi đã đọc điều này có thể đạt được với lookahead hoặc lookbehind nhưng tôi vẫn không thể làm cho nó hoạt động. Tôi chắc chắn rằng tôi đang làm điều đó sai vì regex vẫn phù hợp. Và có, tôi đã chơi xung quanh/gỡ lỗi các nhóm, thay đổi $ 0 thành $ 1, v.v.

Bất kỳ ý tưởng nào?

+0

Tôi tự hỏi có cần thêm bao nhiêu câu hỏi về chủ đề này để mọi hoán vị của tựa đề đã tồn tại trên SO và mọi người bắt đầu sử dụng một trong các giải pháp đã – Tomalak

+1

Tôi đã dành rất nhiều thời gian với cái này và đã làm một số nghiên cứu, nhưng vẫn không thể tìm ra. Ngăn xếp tràn đã giúp tôi tìm ra giải pháp và bây giờ cả cộng đồng có thể tận dụng những câu trả lời này. –

+0

Tôi cũng thách thức bạn chỉ cho tôi một giải pháp cho vấn đề này đã có trên SO với một "tiêu đề bị" –

Trả lời

9

Bạn đang gần. Bạn có thể sử dụng "lookbehind tiêu cực" như vậy:

(?<!href=")http:// etc 

Tất cả kết quả trước bởi href sẽ bị bỏ qua.

+0

cảm ơn, chính xác đây là điều tôi cần ... tôi đã rất thân thiết! –

+0

Tôi luôn mang theo "Regular Expression Pocket Reference" với tôi ;-) –

0

Có lẽ phân tích cú pháp html sẽ phù hợp hơn cho bạn (ví dụ: htmlparser). Sau đó, bạn có thể có các nút html và chỉ "liên kết" các liên kết trong văn bản chứ không phải trong các thuộc tính.

0

Nếu bạn phải tự cuộn, hãy xem xét các thuật toán/mẫu được sử dụng trong triển khai Mã nguồn mở của Markdown, ví dụ: MarkdownJ.

1

Nếu bạn muốn sử dụng regex, (mặc dù tôi nghĩ phân tích cú pháp thành XML/HTML trước tiên là mạnh mẽ hơn) Tôi nghĩ rằng điều này có ý nghĩa hay không. Lần đâm đầu tiên có thể là thêm điều này vào cuối regex của bạn:

(?!</a>) 

Ý nghĩa: không khớp nếu có thẻ đóng ngay sau đó. (Điều này có thể được tinh chỉnh mãi mãi, tất nhiên). Điều này không hoạt động tốt, tuy nhiên, vì cho chuỗi

<a href="...">http://example.com/</a> 

regex này sẽ cố gắng để phù hợp với "http://example.com/", thất bại do các lookahead (như chúng tôi hy vọng), và sau đó backtrack trình độ tham lam để có kết thúc và khớp với "http://example.com" thay vào đó, không có sau nó.

Bạn có thể khắc phục sự cố sau bằng cách sử dụng possessive qualifier trên +, * và? các toán tử - chỉ cần gắn dấu + sau chúng. Điều này ngăn cản họ theo dõi lại. Điều này có lẽ tốt cho lý do hiệu suất, là tốt.

này làm việc cho tôi (chú ý ba thêm + 's):

String r = "http(s)?://([\\w+?\\.\\w+])++([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&amp;\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*+)?+(?!</a>)"; 
1

Nếu bạn thực sự muốn làm điều đó với regex, hơn:

String r = "(?<![=\"\\/>])http(s)?://([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&amp;\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?"; 

ví dụ hãy kiểm tra xem URL có không tuân theo a = "hoặc />

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