小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

理解 Java 正則表達(dá)式怪異的 \ 和 \\,讓您見怪不怪 | 隔葉黃鶯 Unmi Bl...

 ihacku 2012-06-13

理解 Java 正則表達(dá)式怪異的 \\ 和 \\\\,讓您見怪不怪



Java 語言里的幾大變革,一為 jdk1.4 引入的正則表達(dá)式,jdk1.5 引入的泛型。沒有泛型之前有不少人曾想方設(shè)法從編譯器入手讓 Java 支持泛型。說到泛型  Perl 無疑是該方面的佼佼者,雖然我們不要求 Java 的正則表式能像 Perl 那樣可以用來寫詩,但至少能有 JavaScript 好用些,可是還不如。JavaScript 里 // 兩斜線一框就是一個(gè)模式,分組和后向引用更方便,當(dāng)然前面那兩家伙是動(dòng)態(tài)的,不太好比。

復(fù)雜的用法不說,且說 Java 的正則表達(dá)式在匹配點(diǎn)(.)  和斜杠(\),表達(dá)式要分別寫作 \\. 和 \\\\, 難看些,不好理解。幸好還有些人記住了,匹配點(diǎn)(.) 或  {、[、(、?、$、^ 和 * 這些特殊符號(hào)要要前加雙斜框,匹配 \ 時(shí)要用四斜杠,這確實(shí)能讓你包走天涯的。那么為什么是這樣呢,不是一個(gè)斜杠、三個(gè)或更多呢,所以知其然還要知其所以然,這樣才能每次心中有數(shù),方能以一變 應(yīng)萬變。

首先,Java 的正則表達(dá)式語法說明參見:http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html。

用 最簡單的例子來說明問題吧,不創(chuàng)建 Pattern、Matcher 等對(duì)象,就看 String 對(duì)象的 replaceAll(String regex, String replacement),它第一個(gè)參數(shù)接收的就是一個(gè)正則表達(dá)式,我們可以在 IDE 里的調(diào)試器中看 "a.b".replaceAll(".","") 能不能得到你期望的結(jié)果。

先說為什么像點(diǎn)號(hào)(其他的特殊符號(hào)還有引號(hào)中的 "{、[、(、?、$、^ 和 *")前面要加雙斜杠,注意逗號(hào)(,) 不是這一類特殊字符,因?yàn)樗粫?huì)出現(xiàn)在中括號(hào)或花括號(hào)中。

顯然,如果直接執(zhí)行

1
"a.b".replaceAll(".","");  //返回空字符串

得到的值不是你想要的結(jié)果,成空字符串了,因?yàn)辄c(diǎn)號(hào) "." 匹配了所有的字符,那要只匹配點(diǎn)號(hào)該如何呢,對(duì)的,雙斜杠

1
"a.b".replaceAll("\\.","");  //對(duì)的,得到的是 ab

那為什么是雙斜杠呢?這個(gè)很簡單,因?yàn)辄c(diǎn)號(hào)(.),是個(gè)特殊字符,所以它前面需要需要加個(gè)斜杠給它轉(zhuǎn)義,你要真只用一個(gè)斜杠來轉(zhuǎn)義,問題就來了,提示你:

java regex slash

Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\),也就是 Java 不認(rèn) \. 序列,所以還需要前面再加一道杠給其后的斜杠轉(zhuǎn)義出一個(gè)斜杠給點(diǎn)號(hào)(.) 用,也就是在 Java 字符串看起來是 “\\.”, 但作為正則表達(dá)式來說就是 “\.”,這于其語言的正則表達(dá)式是一致的。

也 就是說 Java 的正則表達(dá)式字符串有兩層次的意義,那就是 Java 字符串轉(zhuǎn)義出符合正則表達(dá)式語法的字符串,“\\.”, 轉(zhuǎn)義后交給正則表達(dá)式的就是 “\.”,這是符合傳統(tǒng)的。因?yàn)槲覀兤綍r(shí)字符串轉(zhuǎn)義后直接用于輸出,所以帶來不少誤解,這里的最終的正則表達(dá)式就是 Java 字符串的輸出。

java regex slash 1

細(xì)心的同志一定能看到在調(diào)試器里的顯示,看我們寫成的“\\.”, 在調(diào)試器里顯示的是 “\\\\.”,說的是如果我們要得到 “\\.”,這樣的輸出那 Java 的字符串就必須寫成 “\\\\.”, 兩個(gè)斜杠轉(zhuǎn)義出一個(gè)斜杠。

好 的,理解了上面的由來,我們來看看用四個(gè)斜杠來匹配一個(gè)斜杠的原理。主要原因是斜杠 \ 本身就是用于轉(zhuǎn)義別的字符的,當(dāng)然它的架子不是一般的大。因?yàn)檎齽t表達(dá)式串就是 Java 字符串的輸出,正常思維在正則表達(dá)式里匹配斜杠用 “\\”, 那么在 Java 程序里向控制臺(tái)輸出 “\\”雙斜杠該如何寫呢,對(duì)了,就是 “\\\\”,就這么簡單。

再一次從錯(cuò)誤里找下原因吧,假如我們寫成:

1
"a\\b".replaceAll("\", "");

報(bào)什么錯(cuò)呢?String literal is not properly closed by a double-quote,因?yàn)樾备馨哑浜蟮碾p引號(hào)給轉(zhuǎn)義了,當(dāng)然字符串是未結(jié)束。再給它加個(gè)斜杠又如何呢?

1
"a\\b".replaceAll("\\", "");

Java 的語法是通過了,但是執(zhí)行正則表達(dá)式不干了,你轉(zhuǎn)義出來的交給正則表達(dá)式的一個(gè)斜杠,叫它情何以堪,該去轉(zhuǎn)義誰呢?所以運(yùn)行時(shí)異常報(bào) An exception occurred: java.util.regex.PatternSyntaxException。

如果寫成三個(gè)斜杠呢?

1
"a\\b".replaceAll("<a>\\\</a>", ""); //與單個(gè)斜杠是一樣的異常,掛單的斜杠把雙引號(hào)給轉(zhuǎn)義了

所以這樣推來推去也是該寫成

1
"a\\b".replaceAll("<a>\\\\</a>", "");

對(duì)于正則表達(dá)式看到的就是 “\\”,哪種語言的正則表達(dá)式要的也是這個(gè),也是第一個(gè)斜杠轉(zhuǎn)義了第二個(gè),第三個(gè)轉(zhuǎn)義了第四個(gè),最終就是 “\\”,正則表達(dá)式里轉(zhuǎn)互相轉(zhuǎn)義一下就是 “\”了。

我原來理解還只是停留下轉(zhuǎn)義啊,再轉(zhuǎn)義的基礎(chǔ)上,隨著寫這篇才更加理解到其中要義的,才發(fā)現(xiàn),原來 Java 的正則表達(dá)式和其他語言的正則表達(dá)式語言是統(tǒng)一的。只要記住一點(diǎn),你要想的正則表達(dá)式字符串是什么,而正則表達(dá)式字符串就是 Java 字符串的的輸出結(jié)果,你就知道應(yīng)該怎么寫了

最后來看下 Eclipse 調(diào)試器里僅匹配單個(gè)斜杠時(shí),IDE 里顯示的有多瘋狂:

java_regex_slash_3.jpg

這讓你體驗(yàn)到四個(gè)斜杠又何其多也。注:全文中的斜框標(biāo)準(zhǔn)意義上應(yīng)該叫做反斜杠,在此就不作全文替換了。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多