【问题标题】:PowerShell String Formatting: Why is the colon character causing my variable's value to be blank?PowerShell 字符串格式:为什么冒号字符导致我的变量值为空白?
【发布时间】:2011-12-05 13:42:48
【问题描述】:

我正在查看下一个 WinRM 和 PowerShell 3 即将推出的内容,并查看了重大更改列表,发现了一些我以前从未见过的东西。

例子是:

$server = "msp42"
$status = "online"
"$server: $status"

结果输出是:

在线

好的,我以前从未遇到过这种情况,也不知道为什么冒号会导致问题。 文档中建议的解决方案是放置一个空格(这很愚蠢,因为您会更改输出):

"$server : $status"

另一个建议是使用这种格式(对我来说是新的!):

"${server}: $status"

最后的建议是做一个我熟悉并一直使用的表达式:

"$($server): $status"

所以,我要向您的 PowerShell 专家提出以下问题:

  1. 那个冒号到底是怎么回事?它什么吗?

  2. ${variable} 语法到底是什么?是严格处理冒号还是有一些简洁的功能?

【问题讨论】:

    标签: powershell


    【解决方案1】:

    冒号是变量名的有效字符,例如在$Env:PATH等中

    您也可以使用以下选项

    $server`: $status
    

    或者,在某些情况下,格式字符串更具可读性:

    '{0}: {1}' -f $server, $status
    

    回到冒号。对应于 PSDrive 上的项目的变量名称有一种特殊情况:

    $Env:Foo           # equivalent to the contents of Env:\Foo
    $Function:C:       # equivalent to the contents of Function:\C:
    ${C:\autoexec.bat} # ... you get the picture
    

    语法${} 的存在是为了能够指定变量名,否则这些变量名会使用为语法的其他部分保留的字符。您可以将其视为与标识符前面的 C# 的 @ 相似(但更强大)。请参阅上面在变量名称中使用\ 的位置,因为$Drive:Item 仅适用于驱动器上的当前容器(或非分层容器的根,如EnvAliasFunction)。

    另一个变量名通常是无效语法的例子:

    PS> $+
    The term '$+' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
    spelling of the name, or if a path was included, verify that the path is correct and try again.
    At line:1 char:1
    + $+
    + ~~
        + CategoryInfo          : ObjectNotFound: ($+:String) [], CommandNotFoundException
        + FullyQualifiedErrorId : CommandNotFoundException
    
    PS> ${+} = 5
    PS> ${+}
    5
    PS> Get-Variable +
    
    Name                           Value
    ----                           -----
    +                              5
    

    【讨论】:

      【解决方案2】:

      归因:
      以下答案复制自 Tomas Restrepo 的博客https://winterdom.com/2008/02/20/watchoutforinpowershell

      这是前几天我在 Windows PowerShell 脚本中遇到的问题。假设您有变量 $user 和 $machine,并且想要打印一个字符串,它们的值用冒号 (':') 分隔。

      你显然可以使用字符串连接来做到这一点:

      $user = 'tomasr' 
      $machine = 'arcano' 
      
      write ($user + ':' + $machine)
      

      这行得通,但 PowerShell 不支持那个不错的字符串插值功能吗?为什么,是的!那么我们为什么不直接重写它:

      write "$user:$machine"
      

      但是等等!如果你运行最后一行,你得到的只是 $machine 变量的值...... $user 去哪儿了?

      答案是冒号在 PowerShell 变量名称中具有特殊含义:它用于将变量与特定范围或命名空间相关联。 PowerShell定义了一些范围,例如脚本和全局;例如,一个全局变量可能被命名为 $global:var。

      但是我们不是在其他地方也看到过这种语法吗?当然,$env:PATH 怎么样?一样;除了这里 env 本身不是一个范围,而是一个 PSDrive。所以':'之前的部分可以是由 PS 或 PSDrive 定义的实际范围。哎呀,您甚至可以尝试“${c:autoexec.bat}”之类的方法,然后观看魔术发生!

      所以我们的字符串插值的问题是,当 PowerShell 看到 "$user:$machine" 时,它希望找到一个名为“user”的作用域/psdrive,并希望在“:”之后有一个变量名,但“$”不是有效,并且“用户”也不是范围或 PSDrive,这让 PowerShell 有点困惑。但由于他太绅士了,他只是尽可能地把它修好,忽略了到目前为止的一切,只是毫无怨言地转储 $machine。他很好,但如果你没想到的话,它真的会让你大吃一惊!

      我们可以避免这种情况吗?是的,我们可以通过使用“{}”为 PowerShell 准确地分隔变量名称,如下所示:

      write "${user}:$machine"
      

      Bruce Payette 出色的 Windows PowerShell in Action 第 141 页的第 5.8 节介绍了 PowerShell 中的变量主题,并为我提供了解决此问题的线索。

      【讨论】:

      猜你喜欢
      • 2019-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-27
      • 1970-01-01
      • 2015-03-11
      相关资源
      最近更新 更多