Ciao都——
我正在使用 Powershell 7.2 通過硬體的 CLI 自動化一些硬體配置。我正在使用一個回圈來生成包含“0x”前綴的字串來表示十六進制位元組,但是有一個問題,即在回圈的第一遍之后的任何連續迭代都不會列印“0x”前綴。
以下將產生問題:
function fTest($id)
{
foreach($n in @(1, 2, 3))
{
write-host $id.gettype()
write-host ("{0:x}" -f $id)
$id
}
}
fTest 0x1a
實際輸出:
System.Int32
0x1a
System.Int32
1b
System.Int32
1c
在0xiters 2 和 3 中省略了前綴。
- 為什么會這樣?
- 什么是糾正問題的干凈方法?
我是 PowerShell 菜鳥,所以我很高興收到完全不同方法的建議或示例。
在此先感謝您的幫助!
uj5u.com熱心網友回復:
tl;博士
正如Theo建議的那樣,對您的
$p引數進行型別約束以明確地將其設為數字??(整數) :function fTest($id)->function fTest([int] $id)
將前綴構建
0x到傳遞給的格式字串中-f:"{0:x}" -f $id->'0x{0:x}' -f $id
基于有用的評論:
為什么會這樣?
格式化字串
{0:x},當應用于數字時,只會產生不帶0x前綴的十六進制表示;例如:PS> '{0:x}' -f 10 a # NOT '0xa'如果運算元不是數字,則忽略
:x數字規范:PS> '{0:x}' -f 'foo' foo
您的問題與PowerShell 如何處理傳遞給非型別約束引數的引數有關:
引數
0x1a是不明確的:它可以是一個數字(表示為十六進制常量0x1a,相當于十進制26)或一個字串。- 雖然在運算式決議模式下不會出現這種歧義(字串必須在此處參考),但在引數決議模式下會出現這種情況,其中參考字串是可選的(除非字串包含元字符) - 請參閱概念about_Parsing主題。
在這種情況下,PowerShell 所做的是創建一個混合引數值:該值被決議為一個數字,但它在后臺快取其原始字串表示形式,用于顯示格式,例如:
PS> & { param($p) $p; $p.ToString() } 0x1a 0x1a # With default output formatting, the original string form is used. 26 # $p is an [int], so .ToString() yields its decimal representation
從 PowerShell 7.2.2 開始,令人驚訝且有問題的是,在字串格式化運算子的背景關系中
-f,這樣的混合值被視為字串,即使它自我報告為數字:PS> & { param($p) $p.GetType().FullName; '{0:N2}' -f $p } 0x1a System.Int32 # $p is of type [int] == System.Int32 0x1a # !! With -f $p is unexpectedly treated *as a string*, # !! yielding the cached original string representation.- 此意外行為已在GitHub 問題 #17199中報告。
對傳遞這種混合引數的引數進行型別約束,如頂部所示,避免了歧義:在呼叫時,引數被轉換為引數型別的展開實體(見下一點)。
至于為什么輸出從第二次迭代開始改變:
在這種情況下,快取的字串表示是通過
[psobject]圍繞存盤在 中的數字型別實體的不可見包裝器來實作的$id。當您通過增量操作 (
) 更新此值時,[psobject]包裝器會丟失,并且使用未包裝的數字(原始值 1)更新變數。因此,從第 2 次迭代開始,
$id包含一個未包裝的[int]實體,導致采用{0:x}數字格式并因此產生不帶0x前綴的十六進制表示。第一次迭代產生
0x前綴的唯一原因是它出現在引數的原始字串表示中;如上所述,在這種情況下,數字:x格式說明符被忽略-f,因為運算元(意外地)被視為string。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/466226.html
