[Perl] Regex 正規表達式取代檔案中文字

在遊戲開發過程,我們可能編寫許多設定檔,並用正規表達式處理。
在此篇文章中,討論如何用正規表達式,讓 Perl 取代檔案中的字串。
假設有一個檔案 input.txt,內容為:

a
bb
ccc
$This pen is blue.
..This pen is blue.
Thispen is blue...

現在要將檔案中第四行 "This pen is blue" 前面用 "*" 符號代替 "$",用 "red" 取代 "blue",變成:

*This pen is red.

這讓我想起電影 "王牌大騙子"(Liar Liar)中,主角想把一隻藍色的筆說成是紅色的:



言歸正傳。
在這個情境下,有些人會想到用 Linux 內建指令 sed,以下這種作法是可以的:
#!/usr/bin/perl
use strict;
use warnings;

`sed -i 's/^\\\$This\\\ \\+pen\\\ \\+is\\\ \\+blue/\\\*This\\\ pen\\\ is\\\ red/g' ./input.txt`;
在這裡要特別注意,在 Perl 內利用 backticks (即 ` 符號),執行外部指令 sed 時,整個外部指令,需視為一個雙引號包起的字串,所以跳脫字元的規則需用兩個 backslash: "\\"。
'$' 符號需要用 3 個 backslash 才能跳脫並執行正確。
對此我的理解是:因為 '$' 本身在 Perl 內是具有特殊意義的符號,因此在 Perl 的程式碼裡面先用一個 backslash 跳脫後,'\$' 就成為單純的字元,然後 '\$' 被放到 sed 指令內變成字串的一部份,多加兩個 backslash 跳脫。

根據我測試的結果,在 Perl 內呼叫外部 sed 指令,若要跳脫單一字元,backslash 字元用 3 個最安全。
如果像上述 "\+" 這種正規式,在 perl 內寫成 "\\\+" 執行結果會錯,只需寫成 "\\+" 即可
若直接在 Linux Shell 內執行 sed 指令,使用一個跳脫字元即可。

Perl 本身正規表達式的支援非常完整,我們可以直接在 Linux 的 Shell 透過以下指令來執行取代的動作:

perl -i.bak -p -e 's/^\$This\s+pen\s+is\s+blue/\*This\ pen\ is\ red/g' ./input.txt

如此會產生一個名為 input.txt.bak 的備份檔案(內容與原始的 input.txt 相同),並且將 input.txt 修改成我們期待的內容。



留言