如果包含多个字符串,请执行“ this”,否则执行“ this”

时间:2019-03-28 11:50:39

标签: 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" | select DisplayName
        <#
        if ($p contains more than one string) {
            "Request group Id"
        } else {
            "do this"
        }
        #>            
    }
}

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

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

注意:此答案是对Mathias R. Jessen's helpful answer的补充。

计算命令返回的对象数:

  • Mathias的答案显示了基于 array sub-expression operator@() 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就足够了 强>。 (标量是单个对象,而不是对象的集合。)

    # Even if command ... returns only *one* object, it is safe
    # to call .Count on the result in PSv3+
    (...).Count
    

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


  • 选择@(...).Count ,如果:

    • 您必须保持PSv2兼容
    • 您要计算多个命令(用;或换行符分隔)的输出
    • 对于将整个集合作为单个对象输出的命令(很少见),您想将这些集合计数为1对象
    • 更一般地说,如果需要确保命令输出作为真实的 array 返回,尽管请注意,它的类型始终为[object[]];如果您需要特定元素类型,请使用强制类型转换(例如[int[]]),但是请注意,您并不一定需要@(...);例如,
      [int[]] (...)可以这样做-除非您想防止枚举作为单个对象输出的集合。
  • 选择(...).Count ,如果:

    • 一个命令的输出必须计数
    • 对于将整个集合作为单个对象输出的命令,您要计算这些集合的各个元素;即(...)强制枚举。
    • 用于计数已经存储在变量中的命令输出元素 -当然,您可以简单地省略 (...)并使用{{ 1}}

注意事项:由于a longstanding bug(自PowerShell Core 6.2.0起仍然存在),在 scalar 上访问$var.Count失败,而{ {1}}或更高版本有效-在这种情况下,请使用.Count,但请注意,您可能必须强制枚举。

展示相对于(稀有)命令将集合输出为单个对象的行为的差异:

Set-StrictMode -Version 2

性能注意事项

  • 如果直接计算命令的输出,则@(...)PS> @(Write-Output -NoEnumerate (1..10)).Count 1 # Array-as-single-object was counted as *1* object PS> (Write-Output -NoEnumerate (1..10)).Count 10 # Elements were enumerated. 执行的操作大致相同

    (...)
    • 单核Windows 10 VM的示例输出(绝对时间并不重要,只是数字实际上是相同的):

      @(...)
  • 相比之下,对于已存储在变量中的大型集合$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 } } 会带来大量开销,因为该集合是作为(新)数组(如前所述,您只能Command Seconds ------- ------- (Write-Output $arr).Count 0.352 @(Write-Output $arr).Count 0.365 ):

    @(...)
    • 样本输出;请注意$arr.Count解决方案的速度慢了大约7倍:

      $arr = 1..1e6  # Create an array of 1 million integers.
      
      { ($arr).Count }, { @($arr).Count } | ForEach-Object {
        [pscustomobject] @{
          Command = "$_".Trim()
          Seconds = '{0:N3}' -f (Measure-Command $_).TotalSeconds
        }
      }
      

编码样式注意事项

以下情况适用于@(...)Command Seconds ------- ------- ($arr).Count 0.009 @($arr).Count 0.067 在功能上等效(并且执行相同或性能次要)的情况,即您 选择要使用的结构

Mathias推荐@(...) ,并在评论中指出:

  

在这种情况下,还有另一个理由要明确地包装它-传达意图,即“我们不知道(...)是否是标量,因此不是这种结构”。 / p>

我的投票是@(...).Count

一旦您了解PowerShell(v3或更高版本)将标量视为按需计数1的集合,则可以自由利用该知识,而无需反映中标量和数组之间的区别。语法

  • 在编写代码时,这意味着您不必担心给定命令在情境上是否可以返回标量而不是集合(这在以下情况中很常见) PowerShell,其中使用 single 输出对象捕获命令的输出将按原样捕获该对象,而 2个或更多输出对象将生成 array )。

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

示例:

$p

以上结果:

(...).Count

也就是说,即使类型为# 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访问“其第一个元素”。

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