如何去除字符串中的 "\n" ?
作者丨魚(yú)皮
來(lái)源丨程序員魚(yú)皮
大家好,我是魚(yú)皮,今天分享一個(gè)小知識(shí)。
我最近負(fù)責(zé)的工作是設(shè)計(jì)一個(gè) SQL 解析引擎。簡(jiǎn)單來(lái)說(shuō),就是將一個(gè) SQL 表達(dá)式字符串,解析為一顆對(duì)象樹(shù),從而執(zhí)行查詢(xún)等一系列操作。

在最開(kāi)始,我就遇到了一個(gè)很頭疼的問(wèn)題,用戶(hù)編寫(xiě)的 SQL 語(yǔ)句可能非常不標(biāo)準(zhǔn)!
理想的 SQL 語(yǔ)句,縮進(jìn)很規(guī)范,沒(méi)有多余的字符:
select * from user;
而現(xiàn)實(shí)往往是這樣的:
select * \n
from user;
上述語(yǔ)句不僅縮進(jìn)、換行很隨意,還多了很多無(wú)意義的字符串,比如 "\n" !
因此,想要設(shè)計(jì)一個(gè)通用性強(qiáng)的 SQL 解析引擎,首先要對(duì)字符串進(jìn)行 預(yù)處理,將輸入的 SQL 語(yǔ)句標(biāo)準(zhǔn)化。比如去除回車(chē)、換行、冗余的空格和特殊字符等。
那問(wèn)題來(lái)了,如何去除字符串中的所有 "\n" 呢?注意,這里的 "\n" 并不是換行符,而是由字符 '\' 和字符 'n' 組成的字符串!
# 轉(zhuǎn)換前
select * \n
from user;
# 轉(zhuǎn)換后
select * from user;
首先我想到了兩種思路:
用循環(huán)語(yǔ)句順序掃描每個(gè)字符,通過(guò)當(dāng)前字符和下一個(gè)字符判斷是否為 "\n",再移除。直接用 Java 語(yǔ)言提供的 replaceAll方法,傳入一個(gè)正則表達(dá)式,直接將完整字符串中所有匹配正則的子串替換為空串。
我這里選擇后者,直接用現(xiàn)成的方法會(huì)比較方便,而且借助強(qiáng)大的正則表達(dá)式,可以同時(shí)替換掉多個(gè)冗余字符。
Java 正則表達(dá)式定義:
/*
* 全部替換
* regex 正則表達(dá)式
* replacement 要替換成的新串
*/
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}剛開(kāi)始我想的太簡(jiǎn)單了,直接編寫(xiě)出如下代碼:
str.replaceAll("\n", "");
結(jié)果,并不能順利地替換掉字符串中的 "\n",僅僅是把換行符去掉了!

原因很簡(jiǎn)單,在 Java 字符常量中,反斜杠(\)是一個(gè)特殊的字符,被稱(chēng)為 轉(zhuǎn)義字符,它的作用是用來(lái)轉(zhuǎn)義后面一個(gè)字符,本身不具有實(shí)際意義!
因此,不能用下面這種方式直接輸出反斜杠:

如果想要單獨(dú)輸出一個(gè)反斜杠,需要再加上一個(gè)反斜杠轉(zhuǎn)義:

同理,想要輸出一個(gè) "\n" 字符串,代碼要這么寫(xiě):
System.out.println("\\n")
那不妨試試這個(gè)正則表達(dá)式:
str.replaceAll("\\n", "");
結(jié)果出乎意料,竟然和只用一個(gè)反斜杠時(shí)的效果一樣!僅僅是移除了換行符。

其實(shí),正確的答案應(yīng)該是使用 四個(gè)反斜杠,因?yàn)榉葱备茉?Java 和正則表達(dá)式中都是轉(zhuǎn)義字符!

其中,第一個(gè)斜杠是轉(zhuǎn)義符,第二個(gè)斜杠是斜杠本身,第三個(gè)斜杠又是轉(zhuǎn)義符,第四個(gè)斜杠是斜杠本身。
在 Java 中,輸出 "\n" 字符串需要兩個(gè)反斜杠和一個(gè) 'n',在 Java 的正則表達(dá)式中,要給這兩個(gè)反斜杠分別再分配一個(gè)反斜杠進(jìn)行轉(zhuǎn)義,才能生效。
總而言之,記住一句話(huà):Java 正則表達(dá)式中,匹配一個(gè)反斜杠要用四個(gè)反斜杠!
最后,正則表達(dá)式可是一門(mén)大學(xué)問(wèn),推薦一款學(xué)習(xí)、創(chuàng)建和測(cè)試正則表達(dá)式的在線(xiàn)可視化工具,RegExr。通過(guò)練習(xí)的方式學(xué)習(xí),很快就能入門(mén)啦!

-End-
最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來(lái),可以說(shuō)是程序員面試必備!所有資料都整理到網(wǎng)盤(pán)了,歡迎下載!

面試題】即可獲取