2012-02-02 109 views
10

參照下面的問題 - String.replaceAll single backslashes with double backslashesJava中,正則表達式,需要轉義反斜線在正則表達式

我寫了一個測試程序,我發現結果是在這兩種情況下都是這樣,我是否轉義反斜線或不。這可能是因爲 - \ t是一個公認的Java String轉義序列。 (試試吧,它會抱怨)。 - \ t被視爲正則表達式中的文字標籤。 我有點不確定的原因。

是否有關於在Java中轉義正則表達式的一般指導原則。我認爲使用兩個反斜槓是正確的方法。

我仍然想知道你的意見。

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$")); 
    } 
} 

回答

6

第一種形式\\t將被模式類擴展爲tab char。

第二種形式\t將在Java構建模式之前擴展爲Java的製表符。

最後,你得到一個選項卡字符的方式。

+5

這是正確的,*「我相信」*沒有必要。 ''\\ t「'轉換爲Java字符串中的'」\ t「',這轉換爲正則表達式引擎中的製表符。 '「\ t」轉換爲Java字符串中的製表符,在正則表達式中保持不變。 – Tomalak 2012-02-02 13:53:03

+0

謝謝。我明白。 – RuntimeException 2012-02-02 13:53:03

+0

@Tomalak擺脫了'我相信'一點......對不起... – 2012-02-02 13:55:40

9

轉義序列有兩種解釋:第一種是Java編譯器,然後是正則表達式引擎。當Java編譯器看到兩個斜槓時,它會用一個斜槓替換它們。當斜線後面有t時,Java會用選項卡替換它;當雙斜線後面有一個t時,Java將它留下。但是,由於兩個斜槓已被替換爲單斜槓,因此正則表達式引擎會看到\t,並將其解釋爲選項卡。

我認爲這是更清潔,讓正則表達式解釋\t作爲一個標籤(即用Java編寫"\\t"),因爲它可以讓你看到調試,記錄等過程中其預期的形式表達如果轉換Pattern\t字符串,你會在正則表達式的中間看到一個製表符,並且可能會把它混淆爲其他空格。使用\\t的模式沒有這個問題:他們會用一個斜槓告訴你一個\t,告訴你它們匹配的空白。

+1

謝謝。現在我明白,正則表達式引擎能夠理解'[\ t]'(\ t在空格之後)和'[]'(空格之後的製表符)並對它們進行相同的處理。你認爲我說得對嗎? '[\ t]'雖然看起來更容易理解。所以我必須在Java中使用'[\\ t]'。 – RuntimeException 2012-02-02 14:05:38

+0

@SatishMotwani「必須」一詞太強大了,但讓'\\ t'流向正則表達式是一種很好的做法。 – dasblinkenlight 2012-02-02 14:07:25

6

是的,有關於轉義的一般指導原則:Java源代碼中的轉義序列被Java編譯器(或最終的某個預處理器)取代。編譯器會抱怨它不知道的任何轉義序列,例如\s。當您爲RegEx模式編寫字符串文字時,編譯器將像往常一樣處理該文字,並將所有轉義序列替換爲相應的字符。然後,程序執行時,Pattern類會編譯輸入的字符串,也就是說,它會再次計算轉義序列。 Pattern類知道\s是一個字符類,因此可以編譯一個包含這個類的模式。但是,您需要從不知道此轉義序列的Java編譯器中跳出\s。要做到這一點,您可以避開導致\\s的反斜槓。

總之,您總是需要爲RegEx模式轉義字符類兩次。如果要匹配反斜槓,則正確的模式爲\\\\,因爲Java編譯器會將其編譯爲\\,模式編譯器會將其識別爲轉義的反斜槓字符。

+0

謝謝。我明白。所以你需要在Java中編寫你的'String',以便Pattern引擎獲得它所期望的。我想在將來用Java編寫正則表達式時我必須非常小心。 – RuntimeException 2012-02-02 13:57:03

0

使用org.apache.commons.lang3.StringEscapeUtils.unescapeJava(...),您可以轉義大部分常見的spl。字符和unicode字符(將unicode字符集轉換爲可讀的常規字符)