如果存在名称相同的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"
}
#>
}
}
需要有关注释块中功能的帮助。
答案 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
,如果:
;
或换行符分隔)的输出1
对象。[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。