
1. 一個(gè)被大多數(shù)人忽略的鍵盤符號(hào)′ 到底是什么你可能每天都在鍵盤上敲字但有一個(gè)符號(hào)絕大多數(shù)人從來(lái)沒(méi)有主動(dòng)打過(guò)甚至不知道它的存在——′也就是單個(gè)上標(biāo)的撇號(hào)。它看起來(lái)像一個(gè)小斜杠從左上往右下輕輕一撇懸浮在字符的上方。很多人第一次見到它是在某些外文教材、音樂(lè)譜面、或者歐洲語(yǔ)言的人名里比如法語(yǔ)里的“é”去掉下面的“e”之后剩下的那個(gè)小撇就是它。這個(gè)符號(hào)在Unicode里的正式名稱叫“Acute Accent”中文一般翻譯成“尖音符”或“銳音符”碼位是U00B4。它和反引號(hào)完全是兩回事。反引號(hào)在標(biāo)準(zhǔn)美式鍵盤上位于左上角、數(shù)字1鍵的左邊、Tab鍵的上方和波浪號(hào)~共用一個(gè)鍵位。而′這個(gè)符號(hào)在標(biāo)準(zhǔn)鍵盤上根本沒(méi)有獨(dú)立的按鍵你需要通過(guò)組合鍵或者字符映射表才能打出來(lái)。那為什么值得專門寫一篇東西來(lái)講它因?yàn)樵趯?shí)際工作和生活中這個(gè)小符號(hào)會(huì)以你想不到的方式出現(xiàn)在各種場(chǎng)景里寫代碼時(shí)不小心打錯(cuò)導(dǎo)致程序報(bào)錯(cuò)、做多語(yǔ)言文檔時(shí)被它卡住、處理用戶輸入數(shù)據(jù)時(shí)發(fā)現(xiàn)有人用它冒充單引號(hào)、甚至在社交媒體上看到有人用它來(lái)做特殊的排版效果。我見過(guò)太多人因?yàn)榉植磺濉?、、、‘、’這幾個(gè)長(zhǎng)得像的符號(hào)在調(diào)試上浪費(fèi)了大量時(shí)間。這篇文章適合所有人看——不管你是程序員、文字工作者、數(shù)據(jù)分析師還是只是偶爾需要輸入特殊字符的普通用戶。我會(huì)從最基礎(chǔ)的概念講起把′這個(gè)符號(hào)的來(lái)龍去脈、輸入方法、常見混淆場(chǎng)景、以及實(shí)際使用中的坑全部拆開講清楚??赐曛竽悴粌H能準(zhǔn)確打出這個(gè)符號(hào)還能在遇到相關(guān)問(wèn)題時(shí)快速定位原因。2. 尖音符′的核心概念與鍵盤輸入原理2.1 尖音符的歷史來(lái)源與語(yǔ)言背景′這個(gè)符號(hào)并不是憑空造出來(lái)的。它的學(xué)名叫“尖音符”Acute Accent在語(yǔ)言學(xué)里屬于“附加符號(hào)”Diacritic的一種。附加符號(hào)就是加在字母上面或下面的小標(biāo)記用來(lái)改變字母的發(fā)音或者區(qū)分詞義。尖音符最早可以追溯到古希臘語(yǔ)當(dāng)時(shí)用來(lái)標(biāo)記音高重音。后來(lái)拉丁語(yǔ)系的語(yǔ)言大量采用它比如法語(yǔ)、西班牙語(yǔ)、葡萄牙語(yǔ)、意大利語(yǔ)、加泰羅尼亞語(yǔ)等等。在法語(yǔ)里é和e是兩個(gè)不同的字母發(fā)音不同詞義也可能不同。比如“élève”學(xué)生和“eleve”在沒(méi)有尖音符的情況下就是拼寫錯(cuò)誤。西班牙語(yǔ)里的á、é、í、ó、ú同樣承載著重音信息去掉尖音符會(huì)改變單詞的重音位置甚至改變意思。葡萄牙語(yǔ)里的′用來(lái)標(biāo)記開音元音和另一個(gè)符號(hào)^揚(yáng)抑符形成對(duì)立。所以′這個(gè)符號(hào)本身是有明確語(yǔ)言學(xué)功能的它不是一個(gè)裝飾品。當(dāng)你在鍵盤上單獨(dú)打出它的時(shí)候它就是一個(gè)獨(dú)立的字符Unicode給它的碼位是U00B4。注意它和“組合用尖音符”U0301不同。組合用尖音符是打在字母后面自動(dòng)疊加到前一個(gè)字母上比如輸入e然后輸入U(xiǎn)0301就會(huì)顯示成é。而U00B4是一個(gè)獨(dú)立的間距字符它自己占一個(gè)位置不會(huì)和前面的字母合并。這個(gè)區(qū)別非常關(guān)鍵。很多人在Word或者網(wǎng)頁(yè)表單里輸入′以為它會(huì)自動(dòng)變成重音符號(hào)加到字母上結(jié)果發(fā)現(xiàn)它就是一個(gè)孤零零的小撇和后面的字母各占各的位置。這就是因?yàn)檩斎敕ńo出的是U00B4而不是U0301。2.2 標(biāo)準(zhǔn)鍵盤布局中′的位置邏輯標(biāo)準(zhǔn)美式鍵盤US QWERTY上′沒(méi)有獨(dú)立的物理按鍵。那為什么有些人說(shuō)“我鍵盤上能直接打出來(lái)”因?yàn)樗麄冇玫目赡苁菄?guó)際鍵盤布局或者某些歐洲語(yǔ)言布局。比如美式國(guó)際鍵盤US International里單引號(hào)鍵被設(shè)計(jì)成了“死鍵”Dead Key。你按一下屏幕上什么都不顯示再按一下e就會(huì)輸出é。如果你按一下再按一下空格就會(huì)輸出′。這就是死鍵的工作機(jī)制——先按的鍵不立即輸出而是等待下一個(gè)按鍵來(lái)決定組合結(jié)果。在標(biāo)準(zhǔn)美式鍵盤上單引號(hào)鍵直接輸出的是U0027撇號(hào)/apostrophe和′完全是兩個(gè)碼位。很多人以為它們是一樣的其實(shí)不是。U0027是ASCII字符U00B4是Latin-1擴(kuò)展字符。在編程中這兩個(gè)字符絕對(duì)不能混用。那在標(biāo)準(zhǔn)鍵盤上怎么打出′常見的方法有幾種Alt代碼法按住Alt鍵在小鍵盤上依次輸入0180松開Alt鍵就會(huì)輸出′。注意必須用數(shù)字小鍵盤筆記本上沒(méi)有獨(dú)立小鍵盤的話需要開啟Fn組合或者用外接鍵盤。輸入法符號(hào)面板搜狗、微軟拼音、百度輸入法等都有符號(hào)大全功能里面能找到′。字符映射表Windows系統(tǒng)自帶“字符映射表”程序macOS有“字符檢視器”可以可視化地找到并復(fù)制這個(gè)符號(hào)。Unicode輸入法在Linux系統(tǒng)下按CtrlShiftU然后輸入00B4再按回車就能打出′。HTML實(shí)體在網(wǎng)頁(yè)開發(fā)中可以用acute;或者#180;來(lái)表示這個(gè)符號(hào)。2.3 ′與反引號(hào)的本質(zhì)區(qū)別這是最容易混淆的地方必須徹底講清楚。反引號(hào)的Unicode碼位是U0060屬于ASCII字符集在鍵盤左上角和~共用一個(gè)鍵?!涞拇a位是U00B4屬于Latin-1擴(kuò)展字符集沒(méi)有獨(dú)立按鍵。從外觀上看反引號(hào)是從左上往右下傾斜的直線而′是從左下往右上傾斜的短撇。方向剛好相反。你可以把反引號(hào)想象成“往左靠”的斜線′是“往右靠”的斜線。在等寬字體下這個(gè)區(qū)別很明顯但在某些比例字體下兩者可能看起來(lái)很像尤其是字號(hào)小的時(shí)候。在編程中反引號(hào)有特殊用途。比如在JavaScript的模板字符串里用反引號(hào)來(lái)包裹字符串支持多行和變量插值。在Shell腳本里反引號(hào)用來(lái)執(zhí)行命令替換。在Markdown里反引號(hào)用來(lái)標(biāo)記行內(nèi)代碼。而′在這些場(chǎng)景里沒(méi)有任何特殊含義它就是一個(gè)普通字符。如果你在代碼里把反引號(hào)打成了′編譯器或解釋器會(huì)直接報(bào)錯(cuò)而且錯(cuò)誤信息往往不會(huì)直接告訴你“你打錯(cuò)了符號(hào)”而是提示語(yǔ)法錯(cuò)誤讓你找半天。我個(gè)人的經(jīng)驗(yàn)是在代碼編輯器里把字體設(shè)置成等寬字體并且開啟“顯示不可見字符”功能這樣反引號(hào)和′的區(qū)別會(huì)非常明顯。另外很多現(xiàn)代編輯器會(huì)把反引號(hào)高亮顯示而′不會(huì)這也是一個(gè)快速判斷的方法。3. 不同系統(tǒng)和場(chǎng)景下打出′的完整實(shí)操3.1 Windows系統(tǒng)下的多種輸入方案在Windows上打出′最直接的方法是Alt代碼。具體操作確保Num Lock燈亮著按住Alt鍵不放在數(shù)字小鍵盤上依次按0、1、8、0然后松開Alt鍵。屏幕上就會(huì)出現(xiàn)′。這個(gè)方法的原理是Windows的Alt代碼輸入機(jī)制它會(huì)根據(jù)當(dāng)前代碼頁(yè)把數(shù)字轉(zhuǎn)換成對(duì)應(yīng)字符。0180對(duì)應(yīng)的是Latin-1代碼頁(yè)里的′。如果你用的是筆記本沒(méi)有獨(dú)立數(shù)字小鍵盤可以嘗試開啟FnNumLk的組合把部分字母鍵變成數(shù)字鍵。但不同品牌的筆記本操作方式不同有的需要按FnF11有的需要按FnInsert。實(shí)測(cè)下來(lái)聯(lián)想和戴爾的筆記本通常支持這個(gè)功能但惠普的部分型號(hào)不行。如果實(shí)在沒(méi)有小鍵盤可以用下面幾種替代方案。第一種是使用微軟拼音輸入法。切換到微軟拼音按CtrlShiftB打開符號(hào)面板選擇“特殊符號(hào)”分類里面能找到′?;蛘咧苯虞斎搿癹ianyin”或者“acute”候選詞里可能會(huì)出現(xiàn)。不過(guò)這個(gè)方法的缺點(diǎn)是不同版本的輸入法詞庫(kù)不同不一定每次都能找到。第二種是用字符映射表。按WinR輸入charmap回車。在字符映射表里把字體選為“Arial”或者“Times New Roman”然后拉到Latin-1 Supplement區(qū)域找到′點(diǎn)擊“選擇”再點(diǎn)擊“復(fù)制”然后粘貼到你需要的地方。這個(gè)方法雖然步驟多但最可靠任何Windows版本都能用。第三種是用PowerShell或者命令提示符。打開PowerShell輸入[char]0x00B4回車就會(huì)輸出′。然后你可以右鍵復(fù)制。這個(gè)方法適合習(xí)慣命令行的人。注意Alt代碼輸入法依賴于系統(tǒng)的代碼頁(yè)設(shè)置。如果你的系統(tǒng)區(qū)域設(shè)置不是中文簡(jiǎn)體或者英語(yǔ)美國(guó)0180可能對(duì)應(yīng)不同的字符。比如在某些歐洲語(yǔ)言設(shè)置下0180可能輸出其他符號(hào)。如果發(fā)現(xiàn)打出來(lái)的不是′可以嘗試切換到英語(yǔ)美國(guó)鍵盤布局再試。3.2 macOS與Linux下的輸入方式macOS上打出′非常簡(jiǎn)單。按住Option鍵再按e鍵然后松開就會(huì)輸出′。注意這里不需要再按其他鍵直接就是′。如果你按了Optione之后又按了e就會(huì)輸出é。這就是死鍵的行為。macOS的死鍵設(shè)計(jì)非常直觀Optione是尖音符死鍵Option是抑音符死鍵Optioni是揚(yáng)抑符死鍵Optionu是分音符死鍵。如果你不想用死鍵也可以用“字符檢視器”。在菜單欄的輸入法圖標(biāo)里選擇“顯示表情與符號(hào)”或者按ControlCommandSpace打開字符檢視器。在搜索框里輸入“acute”就能找到′雙擊即可插入。這個(gè)方法在寫文檔時(shí)特別方便因?yàn)槟憧梢钥吹椒?hào)的實(shí)際外觀避免打錯(cuò)。Linux下的輸入方式取決于你用的桌面環(huán)境和輸入法框架。在GNOME桌面下可以用CtrlShiftU進(jìn)入U(xiǎn)nicode輸入模式然后輸入00B4按回車或空格就會(huì)輸出′。在KDE下可以用KRunner或者字符選擇器。如果你用的是fcitx或ibus輸入法框架通常也有符號(hào)面板。另外在終端里可以用echo -e \u00B4來(lái)輸出′或者用printf \xC2\xB4。在Linux下還有一個(gè)技巧用Compose鍵。很多Linux發(fā)行版默認(rèn)把右Alt或者菜單鍵設(shè)為Compose鍵。按下Compose鍵然后按再按空格就會(huì)輸出′。Compose鍵的組合規(guī)則和macOS的死鍵類似但更靈活可以自定義。3.3 手機(jī)端與網(wǎng)頁(yè)端的輸入技巧手機(jī)端打出′相對(duì)麻煩一些。iOS系統(tǒng)自帶的鍵盤里長(zhǎng)按單引號(hào)鍵會(huì)彈出多個(gè)變體包括′、、、等。你只需要長(zhǎng)按然后滑動(dòng)到′上松開即可。Android系統(tǒng)也類似長(zhǎng)按單引號(hào)鍵或者逗號(hào)鍵通常會(huì)彈出相關(guān)符號(hào)。不過(guò)不同品牌的Android輸入法比如三星鍵盤、Gboard、搜狗輸入法彈出的符號(hào)集不同有的可能沒(méi)有′。如果沒(méi)有可以切換到符號(hào)面板在“拉丁擴(kuò)展”或者“特殊符號(hào)”分類里找。網(wǎng)頁(yè)端輸入′最推薦的方法是使用HTML實(shí)體。如果你在寫網(wǎng)頁(yè)或者博客可以直接在HTML源碼里寫acute;瀏覽器會(huì)渲染成′。或者用數(shù)字實(shí)體#180;。在Markdown里可以直接粘貼′字符因?yàn)镸arkdown本身支持Unicode。如果你在填寫網(wǎng)頁(yè)表單時(shí)發(fā)現(xiàn)無(wú)法輸入′可以先用記事本打好再?gòu)?fù)制粘貼進(jìn)去。提示在移動(dòng)端輸入′時(shí)注意不要和單引號(hào)混淆。很多輸入法的長(zhǎng)按彈窗里′和挨得很近容易點(diǎn)錯(cuò)。建議放大鍵盤或者用滑動(dòng)選擇的方式確保選中的是′。4. 尖音符′在實(shí)際場(chǎng)景中的常見問(wèn)題與排查4.1 編程開發(fā)中的符號(hào)混淆問(wèn)題在編程中′和、的混淆是最常見的問(wèn)題之一。我見過(guò)不少新手在寫JavaScript模板字符串時(shí)把反引號(hào)打成了′結(jié)果代碼報(bào)錯(cuò)“Unexpected token”或者“Invalid or unexpected token”。錯(cuò)誤信息不會(huì)直接告訴你“你打錯(cuò)了符號(hào)”而是指向一個(gè)看起來(lái)沒(méi)問(wèn)題的地方讓人摸不著頭腦。舉個(gè)例子正確的模板字符串寫法是const name 張三; const greeting 你好${name}; console.log(greeting);如果你把反引號(hào)打成了′代碼變成const greeting ′你好${name}′;這時(shí)候JavaScript引擎會(huì)認(rèn)為′是一個(gè)非法字符直接拋出SyntaxError。但錯(cuò)誤位置可能指向′所在的行也可能指向下一行取決于引擎的實(shí)現(xiàn)。排查的時(shí)候你需要仔細(xì)看錯(cuò)誤信息里的列號(hào)然后檢查那個(gè)位置的字符是不是′。在Shell腳本里反引號(hào)用于命令替換比如current_datedate %Y-%m-%d echo $current_date如果把反引號(hào)打成′Shell會(huì)把它當(dāng)作普通字符命令替換不會(huì)執(zhí)行輸出結(jié)果會(huì)變成字面量。這種錯(cuò)誤不會(huì)報(bào)錯(cuò)但結(jié)果完全不對(duì)排查起來(lái)更麻煩。在SQL里單引號(hào)用于包裹字符串反引號(hào)在MySQL里用于包裹標(biāo)識(shí)符比如表名、列名。′在SQL里沒(méi)有任何特殊含義如果誤用會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤。比如SELECT * FROM users WHERE name 張三;如果把反引號(hào)打成′MySQL會(huì)報(bào)語(yǔ)法錯(cuò)誤。如果把單引號(hào)打成′同樣會(huì)報(bào)錯(cuò)。我的建議是在代碼編輯器里把字體設(shè)置為等寬字體并且開啟“顯示不可見字符”或者“高亮特殊字符”功能。VS Code、Sublime Text、Atom等編輯器都支持這個(gè)功能。另外可以安裝一些插件比如“Trailing Spaces”或者“Unicode Highlight”它們會(huì)把容易混淆的Unicode字符高亮顯示讓你一眼就能看出來(lái)。4.2 多語(yǔ)言文檔處理中的編碼問(wèn)題在處理多語(yǔ)言文檔時(shí)′的編碼問(wèn)題也很常見。比如你把一個(gè)包含′的文本文件從UTF-8轉(zhuǎn)換成Latin-1再轉(zhuǎn)換回來(lái)′可能會(huì)變成亂碼。這是因?yàn)椤湓赨TF-8里占兩個(gè)字節(jié)0xC2 0xB4在Latin-1里占一個(gè)字節(jié)0xB4。如果轉(zhuǎn)換過(guò)程中編碼聲明不對(duì)就會(huì)出現(xiàn)亂碼。我遇到過(guò)一個(gè)實(shí)際案例用戶在一個(gè)CSV文件里輸入了′然后用Excel打開發(fā)現(xiàn)′變成了?′。這是因?yàn)镋xcel默認(rèn)用系統(tǒng)區(qū)域編碼中文Windows下是GBK打開CSV而CSV文件實(shí)際是UTF-8編碼?!涞腢TF-8字節(jié)序列0xC2 0xB4在GBK里被解釋成了兩個(gè)字符?和′。解決方法是在Excel里用“數(shù)據(jù)”-“從文本/CSV”導(dǎo)入手動(dòng)選擇UTF-8編碼。另一個(gè)常見問(wèn)題是數(shù)據(jù)庫(kù)存儲(chǔ)。如果數(shù)據(jù)庫(kù)的字符集是Latin-1而你的應(yīng)用程序用UTF-8連接插入′時(shí)可能會(huì)報(bào)錯(cuò)或者變成問(wèn)號(hào)。解決方法是在連接字符串里指定正確的字符集比如characterEncodingUTF-8。如果數(shù)據(jù)庫(kù)已經(jīng)存了錯(cuò)誤的數(shù)據(jù)需要用CONVERT或者CAST函數(shù)來(lái)修復(fù)。注意在處理多語(yǔ)言文本時(shí)盡量統(tǒng)一使用UTF-8編碼。UTF-8是Unicode的標(biāo)準(zhǔn)編碼支持所有字符不會(huì)出現(xiàn)′這種字符丟失或亂碼的問(wèn)題。如果必須用Latin-1要確保所有環(huán)節(jié)的編碼聲明一致。4.3 社交媒體與內(nèi)容創(chuàng)作中的顯示差異在社交媒體和內(nèi)容創(chuàng)作中′的顯示效果也值得注意。比如在Twitter、微博、微信公眾號(hào)等平臺(tái)上′可能會(huì)因?yàn)樽煮w不同而顯示成不同的樣子。有的字體里′比較短有的比較長(zhǎng)有的傾斜角度不同。如果你用′來(lái)做特殊的排版效果比如在標(biāo)題里加一個(gè)′來(lái)裝飾在不同設(shè)備上看到的效果可能不一樣。另外有些平臺(tái)會(huì)自動(dòng)把′轉(zhuǎn)換成或者刪除。比如某些論壇的輸入過(guò)濾器會(huì)把′當(dāng)作非法字符過(guò)濾掉。如果你發(fā)現(xiàn)發(fā)布的內(nèi)容里′消失了可以嘗試用HTML實(shí)體acute;來(lái)代替或者用圖片代替。在內(nèi)容創(chuàng)作中我個(gè)人的經(jīng)驗(yàn)是如果′不是內(nèi)容必需的比如不是外語(yǔ)單詞的一部分盡量不要用它。因?yàn)樗募嫒菪圆蝗缙胀▎我?hào)容易引起顯示問(wèn)題。如果必須用比如寫法語(yǔ)單詞“café”那就用組合字符éU00E9而不是e′U0065 U00B4。組合字符在所有平臺(tái)上都能正確顯示而分開輸入的兩個(gè)字符可能會(huì)被錯(cuò)誤地分開或者合并。4.4 常見問(wèn)題速查表問(wèn)題現(xiàn)象可能原因解決方法代碼報(bào)語(yǔ)法錯(cuò)誤指向看似正常的行把反引號(hào)打成了′檢查該行是否有′替換為Shell命令替換不執(zhí)行把反引號(hào)打成了′替換為或者用$()代替CSV文件用Excel打開出現(xiàn)?′編碼不匹配UTF-8被當(dāng)作GBK用“從文本/CSV”導(dǎo)入選UTF-8數(shù)據(jù)庫(kù)插入′變成問(wèn)號(hào)數(shù)據(jù)庫(kù)字符集不支持改為UTF-8字符集網(wǎng)頁(yè)上′顯示為方框字體不支持該字符換用支持Latin-1擴(kuò)展的字體手機(jī)輸入法找不到′輸入法符號(hào)面板沒(méi)有收錄長(zhǎng)按單引號(hào)鍵或切換輸入法Alt0180打出來(lái)不是′系統(tǒng)代碼頁(yè)不是Latin-1切換鍵盤布局為英語(yǔ)美國(guó)macOS按Optione沒(méi)反應(yīng)輸入法沖突檢查輸入法設(shè)置或改用字符檢視器5. 尖音符′的進(jìn)階用法與個(gè)人實(shí)操心得5.1 用′做特殊排版與視覺(jué)設(shè)計(jì)雖然′的主要功能是語(yǔ)言學(xué)標(biāo)記但在設(shè)計(jì)領(lǐng)域它也可以被用來(lái)做視覺(jué)裝飾。比如在一些極簡(jiǎn)風(fēng)格的海報(bào)里設(shè)計(jì)師會(huì)用′來(lái)代替普通的撇號(hào)因?yàn)椤涞膬A斜角度更柔和看起來(lái)更優(yōu)雅。在品牌Logo設(shè)計(jì)中′有時(shí)被用來(lái)作為字母的裝飾元素比如把“Cafe”寫成“Café”的變體。在網(wǎng)頁(yè)設(shè)計(jì)中′可以用CSS的::before或::after偽元素來(lái)插入比如.title::after { content: \00B4; color: #ff6600; font-size: 1.2em; }這樣可以在標(biāo)題后面加一個(gè)橙色的′作為裝飾。不過(guò)要注意不同瀏覽器和操作系統(tǒng)對(duì)′的渲染可能不同建議在多個(gè)環(huán)境下測(cè)試。在排版軟件里比如Adobe InDesign′可以作為特殊字符插入。InDesign的“字形”面板里可以找到′并且可以調(diào)整它的位置和大小。有些設(shè)計(jì)師會(huì)用′來(lái)模擬手寫體的重音符號(hào)增加文本的靈動(dòng)感。我個(gè)人的經(jīng)驗(yàn)是用′做裝飾時(shí)要控制好數(shù)量和位置。太多會(huì)顯得雜亂太少又看不出效果。通常在一個(gè)標(biāo)題或者一個(gè)短句里用一兩個(gè)就夠了。另外′的顏色要和整體設(shè)計(jì)協(xié)調(diào)不要用太刺眼的顏色。5.2 數(shù)據(jù)清洗中處理′的實(shí)戰(zhàn)技巧在數(shù)據(jù)清洗中′經(jīng)常出現(xiàn)在用戶輸入的數(shù)據(jù)里。比如用戶從某些歐洲語(yǔ)言的網(wǎng)站復(fù)制粘貼數(shù)據(jù)時(shí)可能會(huì)帶入′。這些′如果不處理會(huì)影響數(shù)據(jù)的匹配和統(tǒng)計(jì)。比如你有一個(gè)用戶表里面有的名字是“José”有的名字是“Jose′”這兩個(gè)在字符串匹配時(shí)會(huì)被認(rèn)為是不同的。處理這種情況通常有兩種策略。第一種是規(guī)范化把′替換成對(duì)應(yīng)的組合字符或者直接去掉。比如用Python的unicodedata模塊import unicodedata def normalize_text(text): # 先分解成組合字符 text unicodedata.normalize(NFD, text) # 過(guò)濾掉所有附加符號(hào) text .join(c for c in text if unicodedata.category(c) ! Mn) return text print(normalize_text(José)) # 輸出 Jose print(normalize_text(Jose′)) # 輸出 Jose這段代碼先把文本分解成基字符和附加符號(hào)然后過(guò)濾掉所有附加符號(hào)包括尖音符、抑音符等最后得到純ASCII文本。這個(gè)方法在處理用戶輸入時(shí)非常有效可以統(tǒng)一不同來(lái)源的數(shù)據(jù)。第二種策略是保留′但統(tǒng)一編碼。比如把所有′都替換成U00B4把所有組合用尖音符U0301也替換成U00B4。這樣雖然不能完全消除差異但至少能保證同一類符號(hào)的編碼一致。具體用哪種策略取決于你的業(yè)務(wù)需求。如果′對(duì)業(yè)務(wù)沒(méi)有意義直接去掉最省事。如果′是業(yè)務(wù)的一部分比如語(yǔ)言學(xué)習(xí)應(yīng)用那就需要保留并正確處理。提示在數(shù)據(jù)清洗中不要直接用str.replace來(lái)替換′因?yàn)椤淇赡芤远喾N形式存在U00B4、U0301、U02CA等。建議先用unicodedata.normalize統(tǒng)一形式再做替換。5.3 我踩過(guò)的坑與避坑建議第一個(gè)坑在寫Markdown文檔時(shí)我用′來(lái)代替反引號(hào)結(jié)果代碼塊沒(méi)有正確渲染。Markdown的代碼塊是用三個(gè)反引號(hào)包裹的如果打成′Markdown解析器會(huì)把它當(dāng)作普通文本代碼塊就不會(huì)生效。我當(dāng)時(shí)的錯(cuò)誤是復(fù)制了一段代碼里面包含了′然后手動(dòng)把′改成了但漏改了一個(gè)導(dǎo)致整個(gè)代碼塊渲染失敗。排查的時(shí)候我盯著屏幕看了半天最后用“顯示不可見字符”功能才發(fā)現(xiàn)問(wèn)題。第二個(gè)坑在Excel里用公式處理文本時(shí)′和被當(dāng)作不同的字符。比如我用IF(A1, yes, no)來(lái)判斷單元格是否包含單引號(hào)結(jié)果發(fā)現(xiàn)包含′的單元格返回了“no”。這是因?yàn)椤浜偷拇a位不同。解決方法是改用IF(CODE(A1)180, yes, no)或者用IF(A1CHAR(180), yes, no)。第三個(gè)坑在數(shù)據(jù)庫(kù)遷移時(shí)′的編碼問(wèn)題導(dǎo)致數(shù)據(jù)丟失。我從一個(gè)Latin-1的數(shù)據(jù)庫(kù)導(dǎo)出數(shù)據(jù)然后導(dǎo)入到UTF-8的數(shù)據(jù)庫(kù)′變成了問(wèn)號(hào)。原因是導(dǎo)出時(shí)沒(méi)有指定編碼導(dǎo)入時(shí)默認(rèn)用了UTF-8。解決方法是導(dǎo)出時(shí)用mysqldump --default-character-setlatin1導(dǎo)入時(shí)用--default-character-setutf8mb4并且在導(dǎo)入前把文件轉(zhuǎn)成UTF-8。避坑建議第一在代碼和文檔中盡量用組合字符而不是獨(dú)立的′。比如寫é而不是e′。第二在數(shù)據(jù)交換時(shí)始終明確指定編碼。第三在排查符號(hào)問(wèn)題時(shí)用十六進(jìn)制查看器或者編輯器的“顯示不可見字符”功能直接看碼位不要靠肉眼判斷。第四在團(tuán)隊(duì)協(xié)作中統(tǒng)一符號(hào)使用規(guī)范比如規(guī)定所有代碼里的字符串都用反引號(hào)所有自然語(yǔ)言里的撇號(hào)都用單引號(hào)避免混用。5.4 尖音符′的擴(kuò)展知識(shí)與相關(guān)符號(hào)′只是眾多附加符號(hào)中的一種。和它相關(guān)的還有幾個(gè)容易混淆的符號(hào)了解它們的區(qū)別有助于更準(zhǔn)確地使用′。符號(hào)Unicode碼位名稱外觀特征常見用途′U00B4尖音符從左下到右上法語(yǔ)、西班牙語(yǔ)等U0060反引號(hào)從左上到右下編程、MarkdownU0027撇號(hào)垂直或略傾斜英語(yǔ)所有格、縮寫U2018左單引號(hào)向左彎曲排版、引用U2019右單引號(hào)向右彎曲排版、引用?U02C6修飾符揚(yáng)抑符尖頂音標(biāo)、數(shù)學(xué)?U02DC修飾符波浪號(hào)波浪形音標(biāo)、數(shù)學(xué)這些符號(hào)在不同場(chǎng)景下有不同的用途。比如在排版中左單引號(hào)和右單引號(hào)是成對(duì)使用的而撇號(hào)是通用的。在編程中只有和有特殊含義其他都是普通字符。在語(yǔ)言學(xué)中′和?、?等一起構(gòu)成附加符號(hào)體系。了解這些符號(hào)的區(qū)別可以幫助你在遇到問(wèn)題時(shí)快速定位。比如你在網(wǎng)頁(yè)上看到一段文字里有一個(gè)奇怪的符號(hào)你可以用瀏覽器的開發(fā)者工具查看它的Unicode碼位然后判斷它是什么符號(hào)再?zèng)Q定怎么處理。我個(gè)人在實(shí)際操作中的體會(huì)是符號(hào)問(wèn)題看似小但一旦出錯(cuò)排查成本很高。尤其是在跨平臺(tái)、跨語(yǔ)言、跨編碼的場(chǎng)景下一個(gè)小符號(hào)可能讓你花幾個(gè)小時(shí)甚至幾天的時(shí)間。所以養(yǎng)成規(guī)范使用符號(hào)的習(xí)慣比事后排查要?jiǎng)澦愕枚?。在輸入特殊符?hào)時(shí)盡量用可靠的方法比如字符映射表或者Unicode輸入法不要靠記憶或者猜測(cè)。在復(fù)制粘貼時(shí)注意檢查符號(hào)是否被轉(zhuǎn)換。在團(tuán)隊(duì)協(xié)作中建立符號(hào)使用規(guī)范并且用工具自動(dòng)檢查。這些習(xí)慣一旦養(yǎng)成能幫你省下大量時(shí)間。