雜記 › 技術筆記 › 複製來的文字全是空行和多餘空格?批次清理的順序

複製來的文字全是空行和多餘空格?批次清理的順序

上週接手一份從 PDF 裡擷取出來的參考文獻清單,180 多條。乍看條目齊全,貼進編輯器打開「顯示空白字元」之後全是問題:每行中間夾著排版繼承下來的換行,標題裡有一整串空格,最前面還躲著一個完全看不見的字元,害得第一條和最後一條在排序時跑到莫名其妙的位置。我原本打算一條條手動刪,刪到第 40 條就亂了套——因為我第一個動作是「刪除所有空行」,那一批由空格組成的行立刻變成真正的空行,前面已經處理過的內容又開始變。

看不見的字元不止一種

那次讓我印象最深的教訓是:空白不是「一種東西」,它是好幾種不同的字元,長得一樣但來源和處理方式都不一樣。把它們分清,才知道該開哪個開關。

字元 碼點與寫法 通常從哪來 螢幕上的表現
半形空格 U+0020,程式碼裡 " " 鍵盤直接敲的 窄空白,肉眼最容易認
全形空格 U+3000 中文排版、中文輸入法下打出的空格 約一個漢字寬
不換行空格 U+00A0,HTML 裡常寫成   網頁裡的縮排與「別在這裡斷行」的間隔 看著和普通空格一樣,但會參與字數
定位字元 Tab,U+0009,程式碼裡寫 \t Excel 複製時的欄分隔、程式碼縮排 跳到下一個定位點,寬度不定
換行字元 LF U+000A 即 \n,CR U+000D,Windows 常見 CRLF 行尾;PDF 的每一行排版都會留下痕跡 把一筆記錄切成多行
BOM U+FEFF,UTF-8 下位元組是 EF BB BF 某些編輯器存檔時加在檔案開頭 完全看不見,只讓首行變形

從 C:\Users\name\a.txt 這種路徑組成的欄裡複製出來,問題往往是複合的:欄之間是 Tab,行末是 CRLF,路徑本身還帶反斜線。這時候「刪空格」這種籠統動作完全沒意義,得指名道姓。

順序為什麼會影響結果

清理不是冪等的,前一步會改寫後一步的輸入。我踩過的三個具體坑:

全形空格轉半形必須放在去空格之前。如果先把半形空格刪乾淨,再去做全形轉半形,轉出來的那批新空格就躲過了上一輪,文字裡留下一堆看起來「刪過了卻還在」的空白。

去空行要放在首尾清理之後。由空格或 Tab 組成的行,在工具眼裡並不是空行,它裡面有兩個字元。先刪每行首尾空格,這些行會立刻塌成零長度,下一輪去空行才刪得掉。我做反的那一次,正是先刪空行,結果空行數字紋絲不動,我以為開關沒生效。

去除所有換行必須是最後一步。因為「每行首尾」這個概念在合併成一行之後就不存在了。多行合一以後再去 trim,作用對象是整段的兩端,中間那些原本在行尾的空格全留在原地。

至於「去除所有空格」,我把它歸到危險動作:程式碼縮排、Markdown 的對齊、以及從 Excel 複製來的欄分隔都是靠空格活著的,全刪一次就把一欄資料黏成一團。需要它的時候我先拿十行做小樣。

我現在固定的流程

  1. 打開顯示空白字元,先確認對手是哪一種。這一步不跳過,否則後面全是猜。
  2. 全形空格轉半形。
  3. 去除定位字元(要保留欄結構時改成先轉成空格,別直接刪)。
  4. 去除每行首尾空格。
  5. 合併連續空行為一個,或者完全去除空行——按需要選一個,兩個都開容易把該留的分隔也吃掉。
  6. 核對統計數字。文字清理 處理時統計會即時跟著變,行數差應當等於我預期刪掉的空行數,對不上就回頭查前一步。
  7. 確認沒有隱形字元殘留:  對應的 U+00A0 不在上面任何開關的管轄範圍裡,我一般會專門看一遍。

清理之後才輪到結構化操作。要給每條加序號和前綴,我用 文字行操作;要把這份清單和另一份比對、或者按字序排一遍去掉重複條目,用 文字排序去重。順序固定是「先清理後運算」,因為尾隨空格會讓兩個明明相同的條目被判成不同,去重結果直接失真。

有一類問題清理解決不了

那份文獻清單最後還剩兩條沒救回來:PDF 排版把一筆記錄從中間分頁切斷,第二條的作者名被劈成上下兩半。刪空行只能刪字元,不知道哪兩個半行本來是一句話。

我的處理辦法是手工把它們拼回去,然後接受「這一步必須人來」。同類情況還有斷字連字號,PDF 裡 com- 換行 puter 這種,把換行刪掉之後得到 com-puter,還是錯的,得連字號一起刪。這類問題屬於內容被切碎,不屬於字元多餘。

Q:為什麼刪了空行,匯出還是一堆空行?

因為那些行不是空的,裡面有空格或 Tab。先去每行首尾空格,讓它們塌成真空行,再執行去空行;順序換一下就刪不掉。

Q:從 Excel 複製一欄路徑,貼出來變成一團,怎麼回事?

Excel 用 Tab 分隔欄、用 CRLF 分隔行。想保留一行一條就只處理行、把 Tab 換成你要的分隔符;想保留表格結構就別動 Tab。

Q:首行開頭有個字元刪不掉,怎麼辦?

那是 BOM(U+FEFF),屬於編碼層的問題,文字清理裡沒有對應的開關。我一般重新按無 BOM 的編碼另存一次,而不是拿刪除字元去硬碰。

Q:一次性勾全部清理選項,不是更省事?

省事但不可控。全形轉換和去空格互相製造對象,去空行和 trim 互相依賴,全部勾上之後統計數字變了你也不知道是誰變的。我寧可分兩三輪,每輪只開一兩個開關,看統計確認效果。

Q:清理會把正文裡的字刪少嗎?

選項本身只針對空白字元和標籤,不該動到正文。但「去除所有空格」和「去除 HTML 標籤」這兩項威力大,處理帶中英混排或帶標記的內容時,我一定先拿一小段驗證,再整批做。

回到那份清單:180 多條清理完剩 178 條,少的兩條是我手工拼回去的。我最終記住的不是某個開關的位置,而是這條判斷——空白字元的問題先分類再排序,順序錯了,同一批選項會做出完全不同的結果;而內容被排版切碎的部分,工具幫不上,別指望多勾一個選項能補回來。

📎 相關文章

PNG 壓了三遍只減 426 位元組:無損壓縮的真實邊界 2026-10-22 WebP 轉 PNG 後體積漲了幾倍:什麼時候必須轉,怎麼把漲幅壓住 2026-10-22 截圖縮到四分之一,小字糊成一團的三種原因 2026-10-22 同樣裁 300×300,頭像為什麼總偏右下角半格 2026-10-22 按每月 1.7 倍預估 18 個月,腳本和表格為什麼給出兩個數 2026-10-22