→ hunandy14: 圖1並不是因為解讀不同導致的,而是路徑相關的cmdlet09/28 23:00
→ hunandy14: 會多做一次雙引號的解釋,這個估計是三張圖的bug根源09/28 23:01
→ hunandy14: 多做一次雙引號用說的可能不好解釋,放張圖給你看09/28 23:03

→ hunandy14: 這個邏輯雖然無誤,但是就是個反人類設計09/28 23:07
→ hunandy14: 圖3估計是這個設計實際引發的bug...09/28 23:08
→ hunandy14: 到圖2圖3這一步,明顯是這個設計導致的bug了09/28 23:10
→ hunandy14: 摁...我認為是bug了,太腦殘了這09/28 23:11
→ hunandy14: 圖中的檔案真實路徑是 "D:\test\Test`[1].txt"09/28 23:13
如果邏輯一致就能說是語言特性
要 user 吞下去就算了
但 PowerShell 自己內部處理都搞不定實在太蠢了
下圖是我自己實作以比對名稱的方式遞迴搜尋路徑
https://i.imgur.com/ZK32zgK.png
這樣的結果才是我想要的
可以直接用管道餵路徑其他 cmdlet 如 get-item
※ 編輯: falcon (110.28.1.89 臺灣), 09/29/2024 00:05:02
→ falcon: 網路上都找好久,都沒有比較全面的方案,也只能自己動手了09/29 00:09
→ falcon: 對了,如果是 te`st`[0].txt 呢?數字部分一樣用萬用字元 09/29 00:34
→ falcon: 我試過兩倍量 ` 不管用… 09/29 00:40
→ falcon: 感覺要改成正規表示法才可靠了 09/29 00:42
→ hunandy14: 我猜你應該快摸到他的邏輯了,就是解2次雙引號 09/29 12:03
→ hunandy14: 八成是為了區別那括號到底是字串還是萬用字元 09/29 12:04
→ hunandy14: 寫一個依照萬用字元表添加反引號的函式或許能解 09/29 12:06
→ hunandy14: 圖2應該是吃了這個虧導致的,官方cmdlet自己出bug 09/29 12:08
→ smallreader: 高手過招(眼花撩亂ing 09/29 13:36
我覺得就只是最初開發者的低級失誤
可能 user 用多了,改不了而已
→ hunandy14: 試了一下 Resolve-Path 應該無解。改用GetFullPath吧09/29 14:07
GetFullPath() 不適用於所有 PSDrive 的路徑
例如 HKLM:\
所以我才需要自己寫模組
用於所有 Get-ltem 的使用場景
話說回來 萬用字元
原來就只是要重複做跳脫而已
$literal = 'te`st`[1].txt'
$pattern = $literal -replace '[`\*\?\[\]]', '`$0'
if ($literal -match '[`\*\?\[\]]') {
$pattern = $pattern -replace '[`\*\?\[\]]', '`$0'
}
PowerShell 的萬用字元底層應該是正規表示法
這是轉換失誤的BUG吧,用久了就變語言特性了
就我的理解應該要像下面這麼做
$wildcardPattern | Select-String -Pattern '`?.' -AllMatches |
ForEach-Object { $_.Matches } | ForEach-Object { $_.Value } |
ForEach-Object {
if ($_ -match '`([\[\]])') { '\' + $Matches[1] }
elseif ($_ -match '`(.)') { [regex]::escape($Matches[1]) }
elseif ($_ -match '\*') { '.*' }
elseif ($_ -match '\?') { '.' }
elseif ($_ -match '[\[\]]') { $Matches[0] }
else { [regex]::escape($_) }
} | Set-Variable regexPatternParts
$regexPattern = $regexPatternParts -join ''
而跳脫處理只需要下面這樣
$wildcardPattern = $literal -replace '[`\*\?\[\]]', '`$0'
※ 編輯: falcon (110.28.1.89 臺灣), 09/29/2024 15:02:46
→ falcon: 這樣看起來,如果以cmdlet的處理方式為準的話09/29 15:06
→ falcon: -like 運算子反而才是壞的,他的行為更不規律09/29 15:06
→ falcon: -like能夠同時符合一般的跳脫規則,與cmdlet獨特的規則09/29 15:07
→ falcon: 麻煩了,不知道要按一般邏輯處理跳脫,還是照這反智規則09/29 15:16
※ 編輯: falcon (110.28.1.89 臺灣), 09/29/2024 15:21:06
→ falcon: 看來只能按照一般的規則,將萬用字元模式轉成正規表示法09/29 17:21
→ falcon: 還需要一個參數來決定要不要先把輸入的萬元字元中的``取代09/29 17:21
→ falcon: 為單個`,這樣就能在兩種規則中切換09/29 17:21
※ 編輯: falcon (110.28.1.89 臺灣), 09/30/2024 15:27:01
→ hunandy14: 今天閒著把github上的討論串都看了 2018就有了...10/09 14:23
→ hunandy14: 一個可以不用自己處理邏輯的解法是這樣的10/09 14:24
→ hunandy14: 不過這有效範圍只有到父資料夾名稱10/09 15:07
→ falcon: 我目前是將萬用字元路徑轉成正規表示法,遞迴方法一層用10/09 18:04
→ falcon: -match運算子比對名稱。結果100%可靠。但效率就不高了,遞10/09 18:04
→ falcon: 迴方法只能停止從不正確的子目錄繼續往下尋找路徑,但也要10/09 18:04
→ falcon: 先比對過所有子目錄名稱,才會知道要從哪個目錄往下走10/09 18:04
→ falcon: 這能處理任何一層目錄名稱中的*或?的多重符合10/09 18:08
我有一個想法是用同名的 function 去代替 cmdlet
例如下面這樣
function Get-Item {
$newArgs = $args
# 在此修改 $newargs
# 找出單獨的字串或 -Path, -LiteralPath 參數的引數
# 將其作為路徑擴展為根目錄 ("PSDrive:\") 開頭的完整的路徑
Microsoft.PowerShell.Management\Get-Item @newArgs
}
但不知道 cmdlet 是如何從 $args 中區分字串與參數名稱
由於引號被去掉了,取值也一樣
用 .GetType() 列出類型也都一樣
看起來也不是依照先後順序與開頭字元為準
https://i.imgur.com/uFynvgK.png
※ 編輯: falcon (39.9.131.112 臺灣), 10/09/2024 22:09:05
※ 編輯: falcon (39.9.131.112 臺灣), 10/09/2024 22:10:30
→ hunandy14: 我一開始有想過轉發,只是也不知道如何實現 10/09 23:04
→ hunandy14: 就算參數能實現還有個大魔王管道 10/09 23:04
→ hunandy14: 沒找到可靠的方法估計也只能取捨了 10/09 23:05
→ hunandy14: 然後就是這應該不是完全解,不然這事不會拖6年還沒解 10/09 23:11