跳到主要內容

← 返回部落格

如何移除換行、重複行與空行

從 PDF 複製一段文字貼到別的地方,它常常被拆成一堆短行;貼一份清單,又有一半的列是重複的。這大概是最常見、也最惱人的文字雜務之一。以下教你各種狀況怎麼清,以及背後到底發生了什麼。

一段真的從 PDF 複製出來的文字,清理後。 我們給文字清理工具這一團典型的亂 —— This sentence was / copied out of a / PDF. / 兩個空行 / It has broken lines. —— 並勾選「收合空白」與「刪除空行」。結果保留了行的結構,但把空白修好了:This sentence was 自成一行,空行消失。貼上之前值得知道:什麼都不勾的話,這個工具刻意什麼都不做。 每個勾選框就是一個轉換,所以你能精確決定發生什麼事,而不是按一個含糊的「清理」鈕、順便被改掉你沒想要改的東西。

輸入與輸出,一字不改。 一段典型的 PDF 貼上,丟進我們的文字清理工具,勾選「收合空白」與「刪除空行」:

This  sentence   was
copied out of a
PDF.


It has  broken lines.

變成

This sentence was
copied out of a
PDF.
It has broken lines.

連續空白與空行都消失了,行的結構保留下來。而什麼都不勾時,這個工具刻意什麼都不改 —— 每個勾選框就是一個轉換,所以你不會拿到沒要求過的副作用。

移除換行(把段落接回去)

PDF 與 Email 常把一整段存成很多獨立的行,每行結尾都有一個硬換行。貼進一般編輯器後,它就維持斷開的樣子。要修好,就是把這些行重新接起來:

  • 用空白接——最常用:第一行⏎第二行 變成 第一行 第二行,適合一般文章段落。
  • 直接相連(不留間隔)——適合被切在半途、應該連在一起的資料。

關鍵在於理解:「換行」是一個真實的字元(有時是兩個:歸位字元 + 換行字元)。移除它,其實就是把那些字元換掉。

在比對或提交任何東西之前先重新折行,有一個量得出來的理由。我們把同樣三個詞餵給文字比對工具兩次 —— 一次寫成一行、一次寫成三行,其他什麼都沒動:

−
one two three
+
one
+
two
+
three

每一行回來都被標成「有變動」。對任何以行為單位的工具來說,換行就是內容 —— 這就是為什麼從 PDF 複製出來、帶著硬換行的段落,在 diff、在重複檢查、在資料庫比對裡,永遠對不上它重新折行後的孿生兄弟。

去除重複行

清單類——Email、關鍵字、網址——最容易混進重複。去重複的做法是保留每一行第一次出現、刪掉之後所有重複,這樣能維持原本順序。如果順序不重要,清完再排 A→Z,相同項目自然會排在一起。

對以行為單位的工具來說,刪掉一行重複是成本最低的修改,而我們自己的文字比對工具可以看出為什麼。從三行裡移除一行,回傳的是

alpha
−
beta
 
gamma

而把它加回去,回傳的是

alpha
+
beta
 
gamma

各只有一行被標記,沒被動到的行維持沒有標記 —— 對照上面那個重新折行的例子,那裡是每一行都被標記。「去重複」是在 diff 之前可以安全執行的操作;「重新折行」不是,除非你對兩邊都做。

刪除空行與多餘空白

還有兩個經典:

  • 空行——段落之間留下的空白列,刪掉能讓文字更緊湊。
  • 多餘空白——連續兩個空白,或 Tab 變成一串空白。把每一串壓成一個空白,格式就一致了。

用真實貼上的文字量過。我們把這一段丟進文字清理工具,勾選「收合空白」與「刪除空行」:

This  sentence   was
copied out of a
PDF.


It has  broken lines.

它回傳:

This sentence was
copied out of a
PDF.
It has broken lines.

連續空白與空行都不見了,而行的結構保留下來 —— 而且什麼都不勾時它刻意原樣回傳,因為每個勾選框就是一個轉換。

一次全部搞定,還很隱私

不必手動一個個尋找取代,文字清理器會依合理順序套用——逐行去頭尾空白、合併空白、刪空行、去重複、排序,最後才依你的選擇合併換行——結果即時顯示。全程在你的瀏覽器本機執行,再敏感的文字也不會上傳。

這也是為什麼那些操作是分開的、而不是一個「清理」鈕:你可以刪空行而不收合空白,也可以收合空白而不動行數。一個按鈕就得去猜你要哪一種。

CR、LF 與 CRLF:三種「換行」

那個看不見的換行,並不總是同一個字元。它有三種,分別來自不同作業系統:

  • LF(\n,換行 line feed)——Linux、macOS、Unix 使用。
  • CRLF(\r\n,歸位 + 換行)——Windows 的慣例。
  • CR(\r,單獨使用)——OS X 之前的老 Mac OS,今天已很少見。

多數時候你不會察覺。但當文字在不同系統之間流動,行尾不一致就會出真問題:diff 裡看起來「每一行都改了」、shell 腳本跑出莫名其妙的錯,或整段變成一長行,有時還冒出可見的 ^M。把行尾統一,這些問題一次解決。

同一個機制也解釋了 CR 與 LF。以行為單位的工具比對的是每一行結尾的位元組,所以一個檔案只要換了換行風格,看起來就像整份重寫過 —— 即使看得見的字元一個都沒移動,就跟上面那個「只重新折行就每一行都被標記」一模一樣:

−
one two three
+
one
+
two
+
three

這也是為什麼「統一換行符」要跟任何真正的修改分成兩個 commit,而審查的人會這樣要求你。

軟換行不是換行

一個常見混淆:編輯器為了塞進視窗把長行折起來,那是軟換行——純粹是視覺效果,背後沒有字元。硬換行才是你能刪掉的真實字元。移除換行只會動到硬換行;軟換行會自己重新折行,根本沒有東西可刪。

什麼時候會遇到

  • 整理清單——Email、關鍵字、網址——要匯入時每列剛好一筆。
  • 把一段文字貼進會把它拆碎的表單或聊天視窗。
  • 重複使用前,先清乾淨 Email 簽名檔或貼來的引文。

行尾不一致也是為什麼兩份幾乎相同的檔案並排卻看起來天差地遠——如何比對兩段文字教你看穿雜訊、只盯真正的改動。

相關文字工具