当前位置: 首页 > 知识库问答 >
问题:

PowerShell中的“$myvariable=”和Set-Variable有什么不同?

胡高寒
2023-03-14

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

我使用一种不同的方法来创建变量。

示例:

写入-输出$MyVariable$MyVariable2

结果为218450x5555

这两个变量有什么不同?

共有1个答案

庾鸿飞
2023-03-14

PetSerAl像以前多次一样,在一篇评论中给出了关键的指针(后来帮助改进了这个答案):

从PowerShell Core 6.2.0开始编写。

PowerShell将看起来像数字的未加引号的文字参数解析为数字,并将其包装在“半透明”的[psobject]实例中,该实例的目的是将指定为字符串的精确参数也保留下来。

所谓半透明,是指得到的$MyVariable2:

>

  • 主要是一个数字--一个常规的(未包装的)[int]实例--用于计算;例如,$MyVariable2+1正确返回21846

    • 此外,当您使用.getType()或通过get-membercmdlet询问它的类型时,它显示它是一个数字;换句话说:在这种情况下,PowerShell会假装包装不存在(请参阅下面的解决方法)。

    上下文中的情景行为类似于字符串--返回与指定完全相同的原始参数文本--在以下上下文中:

    >

  • 输出格式,在直接打印到控制台时以及通常使用out-*cmdlet(如out-file(但不包括set-content)和format-*cmdlet)输出格式。

    使用PowerShell的格式运算符-f设置字符串格式(该运算符基于.NET的string.format()方法;例如,“The answer is{0}”-f 42等同于[string]::format('The answer is{0}‘,42))。

    令人惊讶的是,当您调用.ToString()方法($MyVariable2.ToString())并且(因此也)使用set-content时,它的行为不像可展开字符串(“$MyVariable2”)中的字符串。

    请注意,将数字文本指定为命令参数本身就不明确,因为即使是字符串参数通常也不需要引用(除非它们包含特殊字符),因此,例如,1.0之类的参数可能被解释为版本字符串或浮点数。

    PowerShell解决二义性的方法是将这样一个令牌解析为一个数字,然而,该数字在情况下充当字符串[1],如上图所示。

    可以通过键入参数来指示绑定到它的参数是字符串还是数字来完全避免歧义。

    但是,set-variablenew-variablecmdlet的-value参数必须是-[object]类型的,因为它必须能够接受任何类型的值,而且这些cmdlet没有允许您指示目标数据类型的参数。

    解决方案是将-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]:

    PS> $myvariable -is [psobject]
    False  # NO wrapper object
    
    PS> $myvariable2 -is [psobject]
    True  # !! wrapper object
    

    与传统的Shell不同,PowerShell使用丰富的类型,因此,参数文字(如01.2)会立即解析为数字--在本例中为[double],如果按原样使用,则会在输出上产生不同的表示形式,因为--一旦解析为数字--在输出上应用默认的输出格式(其中数字必须再次转换为字符串):

     PS> 01.2
     1.2  # !! representation differs (and is culture-sensitive)
    

    但是,target命令的目的可能最终是将参数作为字符串处理,在这种情况下,您不希望更改输出表示形式。(请注意,虽然您可以通过使用引号(01.2'01.2')来消除字符串中数字的歧义,但在命令参数中通常不需要这样做,就像在传统的shell中不需要那样。)

    正是由于这个原因,使用[psobject]包装器来捕获原始字符串表示并在输出中使用它。

    注意:可以说,更一致的方法是始终将未加引号的文字参数视为字符串,除非在PowerShell命令中绑定到显式数字类型的参数。

    这对于调用外部程序是必要的,因为参数只能作为字符串传递给外部程序。

    您还可以使用PowerShell代码演示该行为,并使用非类型化参数--不过请注意,通常最好显式键入参数:

     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
    

    >

  • $foo是一个非类型化参数,这意味着使用PowerShell在初始解析literal01.2时推断的类型。

    但是,由于该命令(在本例中是脚本块({...})没有为$foo声明参数类型,因此隐式使用的[psobject]包装在输出中显示原始字符串表示。

  •  类似资料:
    • 问题内容: 在另一个问题中,我发布了一个人告诉我,两者之间是有区别的: 和: 在MySQL中。他还提到了MSSQL如何具有批处理范围,而MySQL如何具有会话范围。有人可以为我详细说明吗? 问题答案: 具有 用户定义变量 的概念。 它们是松散类型的变量,可以在会话的某处初始化,并保持其值直到会话结束。 它们前面带有一个标志,如下所示: 您可以使用语句或在查询内部初始化此变量: 在中开发存储过程时,

    • 问题内容: 之间有什么区别? 和 在SQL Server 2008中? 问题答案: 临时表在大多数特性上都与普通表相似,只是它们进入TempDB而不是当前数据库,并且在有限范围后消失(取决于它们是基于会话的表还是全局的Temp表。记录到事务日志中,以及所有涉及性能的信息。otoh,您还可以像在普通表中一样向临时表中添加尽可能多的索引或视图,触发器或其他任何您想要的内容。 表变量是一种快捷的内存表(

    • 本文向大家介绍Set和WeakSet有什么区别?相关面试题,主要包含被问及Set和WeakSet有什么区别?时的应答技巧和注意事项,需要的朋友参考一下 Set 有 forEach keys values 等方法,类数组结构,可以 add 进各种类型,可以用 keys 和 for-in 取出; WeakSet 没有那些方法,只能 add 进对象,没法取出,只能 has 判断。 将它们视为始终去重的数

    • 问题内容: 看到这样的代码片段 我想知道Hashset是否是一种特殊的设置。他们之间有什么区别吗? 问题答案: A 代表通用的“一组值”。A 是对元素进行排序(并由此排序)的集合,a 是对元素进行 不 排序或排序的集合。 A 通常比A 快很多。 通常将A 实现为一棵红黑树(请参阅http://en.wikipedia.org/wiki/Red- black_tree- 我尚未验证sun / ora

    • 问题内容: 和接口之间的根本区别是什么? 问题答案: 是元素的有序序列,而元素是无序的独特列表。 有序集合(也称为序列)。该界面的用户可以精确控制列表中每个元素的插入位置。用户可以通过其整数索引(列表中的位置)访问元素,并在列表中搜索元素。 一个不包含重复元素的集合。更正式地说,集合不包含元素对e1和e2,使得e1.equals(e2)最多包含一个空元素。顾名思义,此接口对数学集合抽象进行建模。

    • 我仔细阅读了Vue文档“深度反应性”和vm的API。$set和Vue.set但我仍然很难确定何时使用哪个。能够区分两者对我来说很重要,因为在我当前的Laravel项目中,我们动态地设置了对象的许多属性。 文档中的区别似乎在于vm使用的语言。$set是“用于Vue实例”,而Vue.set是“用于普通数据对象”,并且Vue.set是全局的: 但是,有一些方法可以添加属性,并在创建实例后使其具有反应性。