2021年8月8日 星期日

Powershell 利用正則表達式 去除雙引號

Powershell 利用正則表達式 去除雙引號

tags: 部落格文章

這幾天遇到一個問題是CSS檔案裏面存在著大量的錯誤與法,顏色的代碼前後被上雙引號了,網頁差不多是15年前的產物了吧,那時候IE還沒這麼嚴苛或是標準還沒訂這麼細是能過得。

Powershell中使用正則表達式

有幾種方式最常見的是 -match 這只能回傳 bool 數值並不是這次要的這次是用了 -replace

還有一個問題是,Powershell 系統內建是 5.1 版,這個版本可不能處理非系統 encoding 和無 BOM的UTF8 這部分怎麼處理可以看之前的文章。簡單說就是升級到 7.1 就完事了。

[PowerShell 如何輸出 不帶BOM的 UTF-8 檔案](https://charlottehong.blogspot.com/2021/04/powershell-bom-utf-8.html

-replace

替代這個真的很好用。廢話不多說直接上代碼演示

$Text = "Copyright (C) Microsoft Corporation. 著作權所有,並保留一切權利。"
$Text -replace "Microsoft", "CHG"

直接就把原本內文中的 Microsoft 替換成 CHG 了。就大概這麼個用法。

其中有一個比較特別的用法是 $1 這個會回傳你的正則條件搜到的東西,就比如說這次的目標是要找到顏色代碼,但是我事先並不知道代碼是多少,我只能寫條件找到代碼,然後代碼要留著我要替除的是前後的引號。比如以下的示範

$ct = '#head_top{color: "#FFFFFF"};'
$dstStr = $ct -replace '"#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})"', '#$1';
$dstStr

如此一來就可以把雙引號給去除了,剩下的工作就是把檔案讀取進來還有寫入。檔案讀取的時候如果需要過濾清單可以參考底下另一個用法。




-match

另外補充一下這個語法,最常見的是用來判斷文本裡面是否有目標字串,結果只會返回 True 跟 False 比如底下這樣的寫法。

# 文本
$Text = "Copyright (C) Microsoft Corporation. 著作權所有,並保留一切權利。"
# 搜尋是否有 Microsoft
$Text -match "Microsoft"

後面的地方是可以寫正則表達式的,有需要再自己嘗試一下。
然後正則搜到的什麼東西可以用 $matches[0] 來檢視

'#FFFFFF' -match '#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})'
$matches[0]

可以獲取顏色的代碼


獲取括號內的內容可以用這樣 (注意裡面的idx是用1)

'#head_top{color: (Abc123$#@%)};' -match '\((.*?)\)'
$matches[1]





進階應用

除了可以用來搜之外,其實還有一個特別的用法,可以用來剔除陣列中的東西

比如說我要排除特定檔名 txt 剩下的都保留,下面是檔案清單。先自己照著創各種不同類型的副檔名,直接創txt然後改副檔名就好。

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----          2021/8/8  下午 01:33              0 main.cpp
-a----          2021/8/8  下午 01:33              0 note.txt
-a----          2021/8/8  下午 01:33              0 README.md

實際上的代碼

$FileItem = Get-ChildItem
$FileItem = $FileItem -notmatch ".txt$"
$FileItem

這樣就自動剔除 txt 結尾的副檔名了。
可以注意到我是用反過的帶有 no 的語法,如果反過來想指定白名單的話是這樣

$FileItem = Get-ChildItem
$FileItem = $FileItem -match ".cpp$|.md$"
$FileItem

可能有人會想到,不對呀 Get-ChildItem 本身就有過濾的 -filter 指令幹嘛還自己寫。雖然結果是一樣的,但其實兩者效能上有一點點區別。

還有最大的一點是能過濾資料夾!本身自帶的過濾器只能過濾附檔名是不能過濾資料夾的,比如說我讀取一個多層資料夾,裡面有一個 “.git” 文件我不想讀,這時候 -nomatch 就很好用了。這東西是用正則去判斷路徑的字串,自由度就非常高了。

沒有留言:

張貼留言