带有格式运算符的 Powershell 颜色格式

lap*_*tah 2 syntax powershell parameter-passing

我在脚本中使用格式运算符,示例如下:

$current = 1
$total   = 1250
$userCN  = "contoso.com/CONTOSO/Users/Adam Smith"

"{0, -35}: {1}" -f "SUCCESS: Updated user $current/$total", $userCN
Run Code Online (Sandbox Code Playgroud)

这 expectedly 显示以下输出:

SUCCESS: Updated user 1/1250 : contoso.com/CONTOSO/Users/Adam Smith

格式运算符用于将目标输出文本保持在原位,当前/总运行数字在 1-99999 之间变化。如果没有格式运算符,我可以像这样突出显示成功行:

Write-Host -BackgroundColor Black -ForegroundColor Green "SUCCESS: Updated user $current/$total: $userCN"

但问题是如何将高亮颜色与格式运算符结合使用?只有-f参数,它不允许颜色参数,因为它Write-Host与最初的不同。

mkl*_*nt0 6

不像其他的贝壳,PowerShell允许通过命令和表达式作为命令的参数仅仅通过括起来在括号内使用,即(...),在分组操作

调用PowerShell命令(cmdlet、脚本、函数)时,输出按原样作为参数传递,作为其原始输出类型。

因此,Theo从评论中给出的解决方案是正确的:

Write-Host -BackgroundColor Black -ForegroundColor Green `
           ("{0, -35}: {1}" -f "SUCCESS: Updated user $current/$total", $userCN) 
Run Code Online (Sandbox Code Playgroud)

也就是说,-f内部的表达式(...)被执行并且它的输出——在这种情况下是单个字符串——作为位置参数传递给Write-Host(隐式绑定到-Object参数)。


请注意,不会需要,$(...)中,次表达式运算,在这种情况下:

(...) 足以包含表达式或命令。

事实上,在某些情况下$(...)可能会无意中修改您的参数,因为它会解开单元素数组

# Pass a single-element array to a script block (which acts like a function).
# (...) preserves the array as-is.
PS> & { param($array) $array.GetType().Name } -array ([array] 1)
Object[]  # OK - single-element array was passed as-is

# $(...) unwraps it.
PS> & { param($array) $array.GetType().Name } -array $([array] 1)
Int32  # !! Single-element array was unwrapped.
Run Code Online (Sandbox Code Playgroud)

主要用途$(...)是:

  • 可扩展字符串中扩展表达式或命令的输出 (字符串插值)

  • 从输出复合语句,如foreach (...) { ... }if (...) { ... }多个语句直接通过管道,之后收集所述输出前面(这(...)确实为好); 但是,您也可以包装此类语句& { ... }(或. { ... }为了直接在调用方的范围内执行而不是在子范围内执行),以便在管道中获得通常的流行为(输出的一对一传递)。

    • 退一步:鉴于您已经可以在变量赋值中使用复合语句作为表达式- 例如,$evenNums = foreach ($num in 1..3) { $num * 2 }- 并且表达式通常被接受为管道的第一段 - 例如,'hi' | Write-Host -Fore Yellow- 令人惊讶的是,目前不适用于复合声明;这个 GitHub 问题询问是否可以解除此限制。

在将参数传递给命令的上下文中:

  • 使用$(...)时,子表达式运算符 仅当你想通过从输出多个命令或(一个或多个)复合语句作为一个参数和/或,如果输出恰好是一个单一对象,想要该对象所使用原样或者,如果它恰好是一个单元素数组(可枚举),您希望它被解包(传递元素本身,而不是数组。

    • 当然,如果您正在构造一个字符串参数,$(...)在该字符串内可能很有用,用于字符串插值 - 例如,Write-Host "1 + 1 = $(1 + 1)"
  • 使用@(...)中,阵列子表达式运算符 仅当要从输出传递多个命令作为参数和/或确保的是,输出变为阵列; 也就是说,输出作为(常规 PowerShell)数组返回,类型为[object[]],即使它恰好包含一个对象。在讲它的方式是$(...)的在单对象输出的情况下的行为:它确保了单个对象输出太成为一个数组。