2012-02-02 35 views
10

Với tham chiếu đến bên dưới câu hỏi - String.replaceAll single backslashes with double backslashesjava, biểu hiện thường xuyên, cần phải thoát khỏi dấu chéo ngược trong regex

Tôi đã viết một chương trình thử nghiệm, và tôi thấy rằng kết quả là đúng trong cả hai trường hợp, cho dù tôi thoát khỏi dấu chéo ngược hoặc không phải. Điều này có thể là do - \ t là chuỗi thoát chuỗi Java được nhận dạng. (Hãy thử \ s và nó sẽ khiếu nại). - \ t được lấy làm tab theo nghĩa đen trong regex. Tôi không chắc chắn lý do.

Có hướng dẫn chung nào về thoát khỏi regex trong Java hay không. Tôi nghĩ rằng việc sử dụng hai dấu gạch chéo ngược là cách tiếp cận chính xác.

Tôi vẫn muốn biết ý kiến ​​của bạn.

public class TestDeleteMe { 

    public static void main(String args[]) { 
    System.out.println(System.currentTimeMillis()); 

    String str1 = "a b"; //tab between a and b 

    //pattern - a and b with any number of spaces or tabs between 
    System.out.println("matches = " + str1.matches("^a[ \\t]*b$")); 
    System.out.println("matches = " + str1.matches("^a[ \t]*b$")); 
    } 
} 

Trả lời

6

Biểu mẫu đầu tiên \\t sẽ được mở rộng thành thẻ tab theo lớp mẫu.

Biểu mẫu thứ hai \t sẽ được mở rộng sang thẻ tab bằng Java trước khi tạo mẫu.

Cuối cùng, bạn cũng sẽ nhận được một thẻ tab.

+5

Điều này là đúng, * "Tôi tin" * là không cần thiết. '' \\ t "' dịch thành '" \ t "' trong chuỗi Java, nó chuyển thành ký tự tab trong công cụ regex. '' \ T "' dịch thành một ký tự tab trong chuỗi Java, vẫn không thay đổi trong regex. – Tomalak

+0

Cảm ơn. Tôi hiểu. – RuntimeException

+0

@Tomalak Đã loại bỏ các _'I tin'_ bit ... xin lỗi về điều đó ... –

9

Có hai cách giải thích các chuỗi thoát đang diễn ra: đầu tiên bởi trình biên dịch Java, và sau đó bằng công cụ regexp. Khi trình biên dịch Java thấy hai dấu gạch chéo, nó sẽ thay thế chúng bằng một dấu gạch chéo đơn. Khi có t sau dấu gạch chéo, Java sẽ thay thế bằng một tab; khi có một t sau dấu gạch chéo kép, Java để nó một mình. Tuy nhiên, vì hai dấu gạch chéo đã được thay thế bằng một dấu gạch chéo đơn, công cụ regexp nhìn thấy \t và diễn giải nó dưới dạng tab.

Tôi nghĩ rằng đó là bụi để cho các regexp giải thích \t như một tab (ví dụ: viết "\\t" trong Java) bởi vì nó cho phép bạn xem các biểu hiện ở dạng dự định của mình trong quá trình gỡ lỗi, khai thác gỗ, vv Nếu bạn chuyển đổi Pattern với \t thành chuỗi, bạn sẽ thấy một ký tự tab ở giữa biểu thức chính quy của bạn và có thể gây nhầm lẫn nó cho các khoảng trắng khác. Các mẫu có số \\t không có vấn đề này: chúng sẽ hiển thị cho bạn một số \t với dấu gạch chéo đơn, cho bạn biết chính xác loại khoảng trống mà chúng khớp.

+1

Cảm ơn. Bây giờ tôi hiểu rằng công cụ regex hiểu cả '[\ t]' (\ t sau dấu cách) và '[]' (tab sau dấu cách) và xử lý chúng giống nhau. Bạn có nghĩ tôi đúng khi nói điều này không? '[\ t]' trông dễ hiểu hơn. Vì vậy, tôi phải sử dụng '[\\ t]' trong Java. – RuntimeException

+0

@SatishMotwani "phải" là một từ quá mạnh, nhưng cho phép '\\ t' chảy vào regexp là một thực hành tốt. – dasblinkenlight

6

Có, có hướng dẫn chung về thoát: Các chuỗi thoát trong nguồn Java của bạn được thay thế bằng trình biên dịch Java (hoặc một số trình tiền xử lý cuối cùng). Trình biên dịch sẽ phàn nàn về bất kỳ chuỗi thoát nào mà nó không biết, ví dụ: \s. Khi bạn viết một chuỗi ký tự cho một mẫu RegEx, trình biên dịch sẽ xử lý chữ này như thường lệ và thay thế tất cả các chuỗi thoát bằng ký tự theo. Sau đó, khi chương trình được thực thi, lớp Pattern biên dịch chuỗi đầu vào, nghĩa là nó sẽ đánh giá các chuỗi thoát khác một lần. Lớp Pattern biết \s là một lớp nhân vật và do đó sẽ có thể biên dịch một mẫu có chứa lớp này. Tuy nhiên, bạn cần phải thoát khỏi \s từ trình biên dịch Java mà không biết chuỗi thoát này. Để làm như vậy, bạn thoát khỏi dấu gạch chéo ngược dẫn đến \\s.

Tóm lại, bạn luôn cần thoát khỏi các lớp ký tự cho các mẫu RegEx hai lần. Nếu bạn muốn đối sánh với dấu gạch chéo ngược, mẫu chính xác là \\\\ vì trình biên dịch Java sẽ làm cho nó \\ trình biên dịch mẫu sẽ nhận ra là ký tự gạch chéo thoát.

+0

Cảm ơn. Tôi hiểu. Vì vậy, bạn cần phải viết 'String' của bạn trong Java để công cụ Pattern nhận được những gì nó mong đợi. Tôi nghĩ rằng tôi sẽ phải rất cẩn thận khi viết regex trong Java trong tương lai. – RuntimeException

0

Với org.apache.commons.lang3.StringEscapeUtils.unescapeJava (...), bạn có thể thoát hầu hết các điểm chung.ký tự và cũng là ký tự unicode (chuyển đổi bảng mã unicode thành ký tự thông thường có thể đọc được)

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