在PowerShell中,“ $ myvariable =“和Set-Variable有什么区别?

时间:2019-03-16 08:17:41

标签: powershell

在学习PowerShell脚本语言时,我尝试使用“写输出”命令来显示变量。

我使用另一种方法来创建变量。

示例:

$myvariable = 0x5555

Set-Variable -Name myvariable2 -Value 0x5555

这两个变量的数据类型为Int32。

当我使用以下命令时,

Write-Output $myvariable $myvariable2

结果是218450x5555

这两个变量有什么区别?

如何显示printf %d %x之类的格式结果?

2 个答案:

答案 0 :(得分:2)

第一个问题已由@PetSerAl在评论中回答。您的第二个问题:

  

如何显示诸如printf%d%x之类的格式结果

使用PowerShell string formatting获得所需的结果。

答案 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}}包装器在输出中显示原始字符串表示形式