Arrays 如果包含多个字符串do“;这";否则";这";

Arrays 如果包含多个字符串do“;这";否则";这";,arrays,powershell,if-statement,count,scalar,Arrays,Powershell,If Statement,Count,Scalar,如果存在名称相同的SCOM组,则尝试生成请求更多信息(组Id)的脚本: function myFunction { [CmdletBinding()] Param( [Parameter(Mandatory=$true)] [string[]]$ObjectName ) foreach ($o in $ObjectName) { $p = Get-SCOMGroup -DisplayName "$o" | sele

如果存在名称相同的SCOM组,则尝试生成请求更多信息(组Id)的脚本:

function myFunction {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [string[]]$ObjectName
    )

    foreach ($o in $ObjectName) {
        $p = Get-SCOMGroup -DisplayName "$o" | select DisplayName
        <#
        if ($p contains more than one string) {
            "Request group Id"
        } else {
            "do this"
        }
        #>            
    }
}
函数myFunction{
[CmdletBinding()]
Param(
[参数(必需=$true)]
[字符串[]]$ObjectName
)
foreach($ObjectName中的o){
$p=获取SCOMGroup-DisplayName“$o”|选择DisplayName
}
}

需要有关注释块功能的帮助。

将值包装在数组子表达式
@()
中,并计算它有多少个条目:

if(@($p).Count -gt 1){"Request group Id"}

注:此答案是补充

计算命令返回的对象数:
  • Mathias的回答显示了一个基于
    @()
    的健壮、与PowerShell v2兼容的解决方案

    # @() ensures that the output of command ... is treated as an array,
    # even if the command emits only *one* object.
    # You can safely call .Count (or .Length) on the result to get the count.
    @(...).Count 
    
  • PowerShell v3或更高版本中可以像集合一样处理标量,因此只需
    (…).Count
    就足够了。(标量是单个对象,而不是对象的集合)

这些方法通常是通用的,但并不总是可互换的,如下所述


  • 选择
    @(…)。计数
    ,如果:

    • 您必须保持PSv2兼容
    • 您想计算多个命令的输出(用
      或换行符分隔)
    • 对于将整个集合作为单个对象输出的命令(这种情况很少见),您希望将此类集合计数为
      1
      object
    • 更一般地说,如果需要确保命令输出作为真正的数组返回,请注意,它的类型总是
      [object[]]
      ;如果您需要特定的元素类型,请使用强制转换(例如,
      [int[]]
      ),但请注意,您不需要严格使用
      @(…)
      ;e、 g.,
      [int[]](…)
      就可以了-除非您想阻止集合作为单个对象输出的枚举
  • 选择
    (…)。计数
    ,如果:

    • 只能计算一个命令的输出
    • 对于将整个集合作为单个对象输出的命令,需要计算此类集合的单个元素;也就是说,
      (…)
      强制枚举
    • 对于已存储在变量中的命令输出元素的计数,当然,您可以省略
      (…)
      并使用
      $var.Count
警告:由于(在PowerShell Core 6.2.0中仍然存在),在
设置StrictMode(版本2
或更高版本)生效时,访问标量上的
.Count
失败-在这种情况下使用
@(…)
,但请注意,您可能必须强制枚举

要演示将集合作为单个对象输出的(罕见)命令的行为差异,请执行以下操作:


性能注意事项

$arr = 1..1e6  # Create an array of 1 million integers.

{ (Write-Output $arr).Count }, { @(Write-Output $arr).Count } | ForEach-Object {
  [pscustomobject] @{
    Command = "$_".Trim()
    Seconds = '{0:N3}' -f (Measure-Command $_).TotalSeconds
  }
}
  • 如果命令的输出是直接计数的,
    (…)
    @(…)
    的执行方式大致相同:

    $arr = 1..1e6  # Create an array of 1 million integers.
    
    { (Write-Output $arr).Count }, { @(Write-Output $arr).Count } | ForEach-Object {
      [pscustomobject] @{
        Command = "$_".Trim()
        Seconds = '{0:N3}' -f (Measure-Command $_).TotalSeconds
      }
    }
    
    • 来自单核Windows 10虚拟机的示例输出(绝对计时并不重要,只是数字几乎相同):

  • 相反,对于已经存储在变量中的大型集合,
    @(…)
    引入了大量开销,因为集合被重新创建为一个(新)数组(如前所述,您只需
    $arr.Count
    ):

    • 样本输出;请注意,
      @(…)
      解决方案的速度大约慢7倍:

      Command       Seconds
      -------       -------
      ($arr).Count  0.009
      @($arr).Count 0.067
      

编码风格注意事项

$arr = 1..1e6  # Create an array of 1 million integers.

{ (Write-Output $arr).Count }, { @(Write-Output $arr).Count } | ForEach-Object {
  [pscustomobject] @{
    Command = "$_".Trim()
    Seconds = '{0:N3}' -f (Measure-Command $_).TotalSeconds
  }
}
以下内容适用于
@(…)
(…)
在功能上等效的情况(或者执行相同的操作,或者性能是次要的),即当您可以自由选择要使用的构造时

# @() ensures that the output of command ... is treated as an array,
# even if the command emits only *one* object.
# You can safely call .Count (or .Length) on the result to get the count.
@(...).Count 
Mathias建议
@(…)。计数
,在评论中说明:

在这个上下文中显式地包装它还有另一个原因——传达意图,即“我们不知道
$p
是否是标量,因此这个构造”

我投票支持
(…)。计数

$arr = 1..1e6  # Create an array of 1 million integers.

{ (Write-Output $arr).Count }, { @(Write-Output $arr).Count } | ForEach-Object {
  [pscustomobject] @{
    Command = "$_".Trim()
    Seconds = '{0:N3}' -f (Measure-Command $_).TotalSeconds
  }
}
一旦您了解PowerShell(v3或更高版本)将标量视为按需计数为1的集合,您就可以自由地利用这些知识,而无需在语法中反映标量和数组之间的区别:

  • 编写代码时,这意味着您不必担心给定命令是否会返回标量而不是集合(这在PowerShell中很常见,在PowerShell中,使用单个输出对象捕获命令的输出会捕获该对象,而两个或多个输出对象会生成一个数组)

  • 作为一种有益的副作用,代码变得更简洁(有时更快)

例如:

# Call Get-ChildItem twice, and, via Select-Object, limit the 
# number of output objects to 1 and 2, respectively.
1..2 | ForEach-Object {

  # * In the 1st iteration, $var becomes a *scalar* of type [System.IO.DirectoryInfo]
  # * In the 2nd iteration, $var becomes an *array* with 
  #   2 elements of type [System.IO.DirectoryInfo]
  $var = Get-ChildItem -Directory / | Select-Object -First $_

  # Treat $var as a collection, which in PSv3+ works even
  # if $var is a scalar:
  [pscustomobject] @{
    Count = $var.Count
    FirstElement = $var[0]
    DataType = $var.GetType().Name
  }

}
上述收益率:

Count FirstElement  DataType
----- ------------  --------
    1 /Applications DirectoryInfo
    2 /Applications Object[]
也就是说,即使是
System.IO.DirectoryInfo
类型的标量对象也将其
.Count
合理地报告为
1
,并允许使用
[0]
访问“其第一个元素”

有关标量和集合的统一处理的更多信息,请参阅