在学习PowerShell脚本语言时,我尝试使用“写输出”命令来显示变量。
我使用另一种方法来创建变量。
示例:
$myvariable = 0x5555
Set-Variable -Name myvariable2 -Value 0x5555
这两个变量的数据类型为Int32。
当我使用以下命令时,
Write-Output $myvariable $myvariable2
结果是21845
和0x5555
。
这两个变量有什么区别?
如何显示printf %d %x
之类的格式结果?
答案 0 :(得分:2)
答案 1 :(得分:1)
PetSerAl,在之前的很多次评论中都给出了关键的指针(后来又帮助改善了这个答案):
自PowerShell Core 6.2.0起编写。
PowerShell解析一个不带引号的文字参数,该参数看起来像一个数字作为一个数字,并将其包装为“半透明” “ [psobject]
实例,其目的是还将指定的确切参数保留为字符串。
通过半透明表示结果$myVariable2
:
主要是数字 -一个常规的(未包装的)[int]
实例-用于计算;例如$myVariable2 + 1
正确返回21846
.GetType()
或通过Get-Member
cmdlet询问其类型时,它还显示该数字;换句话说:在这种情况下, PowerShell会假装没有包装器(请参阅下面的解决方法)。的行为类似于 string -在以下情况下返回与指定内容完全相同的原始参数文字:
输出格式,既可以直接打印到控制台,也可以使用Out-*
cmdlet(例如Out-File
(但不是Set-Content
)和{ {1}} cmdlet。
string 使用-f
, PowerShell's format operator格式化(基于.NET的String.Format()
method;例如,Format-*
等效于'The answer is {0}' -f 42
)
令人惊讶的是,它不会像可扩展字符串([string]::Format('The answer is {0}', 42)
中的字符串一样起作用,并且在您调用"$myVariable2"
方法(.ToString()
)和(因此也)使用$myVariable2.ToString()
。
请注意,将数字文字指定为命令参数本质上是模棱两可的,因为即使 string 参数通常也不需要引号(除非它们包含特殊字符),例如,Set-Content
之类的参数可以解释为版本 string 或浮点数 number 。>
PowerShell解决歧义的方法是将这样的令牌解析为数字,但是,在某些情况下,它充当字符串 [1] ,如上所示。
通过键入参数可以完全避免歧义,以指示绑定到它的参数是字符串还是数字。
但是,1.0
和-Value
cmdlet的Set-Variable
参数必须-必须输入-New-Variable
类型,因为它必须能够接受任何类型的值,并且这些cmdlet没有可让您指示所需数据类型的参数。
解决方案是通过以下方式强制将[object]
参数视为表达式的结果,而不是被视为未引用文字常量将其包含在-Value
中:
(...)
相反,如果您不采用上述解决方案,则有两种选择解开# Due to enclosing in (...), the value that is stored in $myvariable2
# is *not* wrapped in [psobject] and therefore behaves the same as
# $myvariable = 0x55555
Set-Variable -Name myvariable2 -Value (0x5555)
的按需价值:
$myvariable2
检测由# OK: $myvariable isn't wrapped in [psobject], so formatting it as a
# hex. number works as expected:
PS> 'hex: 0x{0:x}' -f $myvariable
hex: 0x5555 # OK: Literal '0x' followed by hex. representation of the [int]
# !! Does NOT work as expected, because $myvariable2 is treated as a *string*
# !! That is, {0:x} is effectively treated as just {0}, and the string
# !! representation stored in the [psobject] wrapper is used as-is.
PS> 'hex: 0x{0:x}' -f $myvariable2
hex: 0x0x5555 # !! Note the extra '0x'
# Workaround 1: Use a *cast* (with the same type) to force creation of
# a new, *unwrapped* [int] instance:
PS> 'hex: 0x{0:x}' -f [int] $myvariable2
hex: 0x5555 # OK
# Workaround 2: Access the *wrapped* object via .psobject.BaseObject.
# The result is an [int] that behaves as expected.
PS> 'hex: 0x{0:x}' -f $myvariable2.psobject.BaseObject
hex: 0x5555 # OK
包裹的值:
最简单的解决方案是使用[psobject]
:
-is [psobject]
(PetSerAl提供了以下不太明显的替代方法:PS> $myvariable -is [psobject]
False # NO wrapper object
PS> $myvariable2 -is [psobject]
True # !! wrapper object
,它绕过了PowerShell的“隐藏包装”技巧。)
[1] 将输入字符串表示形式保留为作为命令参数传递的隐式数字:
不同于传统的shell,PowerShell使用丰富的类型,因此将[Type]::GetTypeArray((, $myvariable2))
之类的参数文字立即 解析为 number -{{1} }在这种情况下,如果按原样使用,则会导致输出不同的表示形式,因为-一旦解析为数字,就会在输出上应用默认的输出格式(其中数字必须再次变成 string ):
01.2
但是, target命令的意图最终可能会将参数视为 string ,在这种情况下,您不希望输出表示更改。
(请注意,虽然您可以使用引号([double]
与 PS> 01.2
1.2 # !! representation differs (and is culture-sensitive)
来使字符串中的数字消除歧义,但通常不需要 中的命令参数,这与传统shell中不需要的方式相同。)
因此,01.2
包装器用于捕获原始字符串表示形式并在输出中使用它。
注意:可以说,一种更一致的方法是总是将 未引用的文字参数视为字符串,除非在PowerShell中绑定了显式数字类型的参数命令。
这是调用外部程序的必要条件,参数只能以字符串形式传递给它们。
也就是说,在将初始解析为数字之后,PowerShell在构建命令行(Windows)/在调用中传递参数(类Unix平台)时必须使用原始字符串表示形式外部程序。
如果不这样做,则可能会无意中更改参数,如上所示(在上面的示例中,外部程序将接收字符串'01.2'
而不是最初传递的[psobject]
)。 / p>
您还可以使用带有 untyped 参数的PowerShell代码演示行为-尽管请注意,通常最好还是显式键入参数:
1.2
01.2
是一个 untyped 参数,这意味着将使用在文本 PS> & { param($foo) $foo.GetType().Name; $foo } -foo 01.2
Double # parsed as number - a [double]
01.2 # !! original string representation, because $foo wasn't typed
的初始解析过程中PowerShell 推断的的类型。
但是,假设该命令(在这种情况下为脚本块($foo
)没有为01.2
声明参数 type ,则{隐式使用的{1}}包装器在输出中显示原始字符串表示形式 。