檔案內容的字串取代

為什麼需要這段程式碼

手動修改幾十個檔案的內容很累。如果只是改一個字還好,但如果要改符合特定規則的文字,手動操作幾乎不可能。這段 Python 腳本就是為了解決這個問題。它能幫你快速搜尋資料夾,找到符合條件的檔案,並用正則表達式進行批次替換。這對處理程式碼版本號、路徑更新或大量文件修改非常有用。

如何開始使用

下載程式碼:
https://github.com/max32002/MaxFontScripts/blob/master/replace_string.py

確保你的電腦已經安裝了 Python 3 環境。你可以透過終端機或命令提示字元來執行它。

基本的文字替換

最簡單的用法是直接替換特定的單字。如果你有一個資料夾叫做 docs,裡面有很多文件要把 Apple 改成 Orange,你可以輸入指令。

python replace_string.py ./docs "Apple" "Orange"

這會掃描 docs 資料夾下的所有檔案。只要看到 Apple 就會換成 Orange。程式會自動過濾無法開啟的檔案。修改成功的檔案會顯示在畫面上。

使用正則表達式處理複雜規則

這段腳本強大的地方在於支援正則表達式。假設你有很多設定檔,裡面的版本號可能是 v1.0 或 v2.5。你想把所有 v 開頭加上數字的版本號都統一改成 v3。你可以利用正則表達式的符號。

python replace_string.py ./project "v\d+" "v3"

這裡的 v\d+ 代表一個 v 後面接一個以上的數字。這比單純的關鍵字搜尋更靈活。它能一次處理所有符合規則的變動。

指定特定的檔案類型

有時候你不想動到資料夾裡的所有檔案。例如你只想修改副檔名是 .conf 的設定檔。這時候可以在指令最後面加上過濾條件。

python replace_string.py ./config "127.0.0.1" "0.0.0.0" "*.conf"

這樣腳本就只會檢查 .conf 結尾的檔案。這能避免誤動到圖片或執行檔。這對保護專案中的其他檔案非常安全。

運作原理與安全機制

腳本在修改時會先建立一個暫存檔。它會逐行讀取原檔案,處理完後寫入暫存檔。如果內容真的有變動,才會取代舊檔案。如果內容完全一樣,就會刪除暫存檔。這種做法能防止程式執行到一半出錯,導致原本的檔案損毀。

使用前的小提醒

雖然腳本有安全機制,但批次修改依然有風險。建議在執行大量替換前,先備份你的資料夾。你可以先拿一個小檔案做測試。確認正則表達式的結果符合預期後,再對整個專案執行。這是一個好習慣。


想試試看對特定目錄下的所有 Markdown 檔案進行標題格式轉換嗎?

實戰演練調整標題層級

假設你寫了很多筆記,但發現一級標題太大了。你想把所有 Markdown 檔案的一級標題改成二級標題。這在整理文件架構時非常有幫助。手動改一百個檔案會耗費太多時間。


具體的執行指令

你可以使用正則表達式來精確定位標題。開啟終端機並切換到腳本所在的目錄。輸入下面的指令。

python replace_string.py ./my_notes "^#\s" "## " "*.md"

這裡的 ^#\s 是關鍵。^ 代表每一行的開頭。# 是我們要找的符號。\s 代表空白鍵。這樣可以確保只會改到真正的標題。它不會動到內文中間出現的井字號。


執行後的結果

程式會掃描 my_notes 資料夾下所有的 .md 檔案。它會把每一行開頭的井字號多加一個。處理完後你會看到螢幕顯示哪些檔案已經被修改。如果檔案裡面沒有符合條件的內容,程式會顯示無變動。


檢查與備份

在執行這類批次修改前,建議先備份資料夾。你可以先複製一份複本出來。或者先對單一檔案執行測試。確認轉換邏輯完全正確。這能避免正則表達式寫錯導致檔案內容亂掉。


正則表達式的基本邏輯

正則表達式其實就是一種文字的「特徵描述」。它用一串特殊的符號,來描述文字長什麼樣子。這在處理大量文件時超級好用。你可以把它想像成一種進階版的搜尋功能。以下整理了最常用的幾組符號。


基礎匹配符號

這些符號用來代表單一個字元或是位置。它們是所有正則表達式的根基。

符號說明範例
.匹配除了換行以外的任何單一字元a.c 可匹配 abc 或 a1c
^匹配字串的開頭^Hello 必須以 Hello 開頭
$匹配字串的結尾done$ 必須以 done 結尾
\轉義符號,用來搜尋原本就有特殊意義的符號\. 用來搜尋真正的點號
[ ]匹配括號內的任一字元[aeiou] 匹配任何一個母音
[^ ]不匹配括號內的任何字元[^0-9] 匹配任何非數字的字元

次數與位置的標記

這些符號接在字元後面。用來指定前面的字元應該出現幾次。

符號說明範例
*出現 0 次或多次ab* 可匹配 a, ab, abb
+出現 1 次或多次ab+ 可匹配 ab, abb (不含 a)
?出現 0 次或 1 次apples? 可匹配 apple 或 apples
{n}剛好出現 n 次\d{3} 匹配 3 個數字
{n,}出現至少 n 次\d{2,} 匹配 2 個以上的數字
{n,m}出現 n 到 m 次\d{2,4} 匹配 2 到 4 個數字

常用字元群組

為了方便縮寫,正則表達式提供了一些常用的預設符號。這能讓你的規則看起來更簡潔。

符號說明同義表達式
\d任何數字[0-9]
\D任何非數字[^0-9]
\w數字、英文字母或下底線[a-zA-Z0-9_]
\s任何空白字元 (空格、Tab、換行)[ \f\n\r\t\v]
\S任何非空白字元[^ \f\n\r\t\v]

實戰應用範例1

把上面的符號組合起來,就能處理生活中的各種需求。你可以參考下面的例子來練習。

驗證手機號碼 (台灣格式)

^09\d{8}$

解釋:開頭必須是 09,後面接剛好 8 個數字。

簡單的電子郵件格式

\w+@\w+\.\w+

解釋:一串字元接 @,再接一串字元,最後接點號跟一段文字。

移除多餘的空白行

^\s*$

解釋:從開頭到結尾都只有空白或沒內容的行。

正則表達式雖然看起來像外星語。但只要拆開來看,邏輯其實很固定。建議先從最基礎的符號開始試。


實戰應用範例2

你的需求是將 com.app.a 修改為 com.app.b。這裡有一個細節需要注意:你不希望誤改到像是 com.lwfd.apple 這種只是剛好開頭一樣的字串。因此,我們在寫正則表達式時,必須把「邊界」考慮進去。


推薦的正則表達式語法

你可以使用下面的規則來進行精確替換:

搜尋目標: com\.app\.a(?=[.;])|com\.app\.a\b

替換內容: com.app.b

這裡有幾個符號的作用說明:

  • \.:因為點號在正則中有特殊意義,所以要加反斜線,代表真正的「點」。
  • (?=[.;]):這是一個前瞻斷言,表示後面必須接著分號或點號,但這部分不會被取代掉。
  • \b:代表單字的邊界,確保 a 後面沒有接其他英文字母。

實際操作指令

使用我們之前討論的 Python 腳本,你可以直接在終端機輸入這行指令:

python replace_string.py ./src "com\.app\.a(?=[.;])|com\.app\.a\b" "com.lwfd.b" "*.java"

這個指令會掃描 src 資料夾下所有的 Java 檔案。它會精確地把 com.app.a; 換成 com.app.b;,也會把 com.app.a.abc 換成 com.app.b.abc


為什麼這樣寫比較安全

如果你只用 com.app.a 當關鍵字,萬一程式碼裡有 com.app.archive,它就會被錯誤地改成 com.app.b rchive,這會導致程式碼壞掉。加上邊界判斷(點號、分號或 \b)可以確保只改到你真正想要變動的部分。

這類替換通常發生在專案重構(Refactor)的時候。如果檔案數量很多,這行指令能幫你省下大約半小時的手動修改時間。