IF 包含多个字符串 do "this" else "this"
IF contains more than one string do "this" else "this"
如果存在具有相同名称的 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"
}
#>
}
}
在评论区中需要有关功能的帮助。
将值包装在数组子表达式中 @()
并计算它有多少条目:
if(@($p).Count -gt 1){"Request group Id"}
注意:此答案补充 。
计算对象的数量return由命令编辑:
Mathias 的回答显示了一个 强大的、PowerShell v2 兼容的解决方案 基于 array sub-expression operator、@()
.
# @() 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
对象.[1]
- 更一般地说,如果您需要确保命令输出 return 作为真正的 数组 编辑,但请注意它总是类型
[object[]]
;如果您需要 特定元素类型 ,请使用强制转换(例如 [int[]]
),但请注意,您并不严格需要 @(...)
;例如,
[int[]] (...)
会做 - 除非你想防止枚举集合输出为单个对象。
选择(...).Count
,如果:
- 只有一个命令的输出必须计算
- 对于将整个集合作为单个对象输出的命令,您想要计算此类集合的单个元素;也就是说,
(...)
强制枚举命令输出。[2]
- 用于计算命令输出的元素已经存储在变量中 - 当然,您随后可以简单地省略
(...)
并使用 $var.Count
警告:由于a longstanding bug(从 PowerShell Core 6.2.0 开始仍然存在),在 标量上访问 .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.
性能考虑:
如果一个命令的输出是直接计数,(...)
和@(...)
执行的差不多:
$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 VM(绝对时间并不重要,只是数字几乎相同):
Command Seconds
------- -------
(Write-Output $arr).Count 0.352
@(Write-Output $arr).Count 0.365
相比之下,对于大型集合 已经存储在变量中 ,@(...)
引入了大量开销 ,因为集合被重新创建为(新)数组(如前所述,您可以 $arr.Count
):
$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
}
}
示例输出;注意 @(...)
解决方案是如何慢 7 倍的:
Command Seconds
------- -------
($arr).Count 0.009
@($arr).Count 0.067
编码风格注意事项:
以下情况适用于 @(...)
和 (...)
在功能上等效(并且执行相同或性能次要)的情况,即当您 自由选择要使用的结构。
Mathias 推荐 @(...).Count
,在评论中指出:
There's another reason to explicitly wrap it in this context - conveying intent, i.e., "We don't know if $p
is a scalar or not, hence this construct".
我投给 (...).Count
:
一旦您了解 PowerShell(v3 或更高版本)将标量视为按需计数为 1 的集合,您就可以自由利用这些知识,而无需在 语法:
编写代码时,这意味着 您不必担心给定的命令 情境 是否可能 return 标量而不是集合(这在 PowerShell 中很常见,其中使用 单个 输出对象捕获命令的输出按原样捕获该对象,而 2 个或更多 个输出对象导致 数组).
作为有益的副作用,代码变得更简洁(有时更快)。
示例:
# 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]
访问“其第一个元素”。
有关标量和集合的统一处理的更多信息,请参阅 。
[1] 例如,@(Write-Output -NoEnumerate 1, 2).Count
是 1
,因为 Write-Output
命令输出一个 单个 对象 -数组 1, 2
- _作为一个整体。因为只输出一个对象,@(...)
将该对象包装在一个数组中,导致 , (1, 2)
,即一个单元素数组,其第一个也是唯一一个元素本身就是一个数组。
[2] 例如,(Write-Output -NoEnumerate 1, 2).Count
是 2
,因为即使 Write-Output
命令将数组输出为单个对象,该数组也用作-是。也就是说,整个表达式等价于(1, 2).Count
。更一般地说,如果 (...)
中的命令仅输出 one 对象,则该对象按原样使用;如果它输出 多个 对象,它们将收集在常规 PowerShell 数组(类型 [object[]]
)中 - 这与通过 [=121 捕获命令输出时得到的行为相同=]变量赋值 ($captured = ...
)。
如果存在具有相同名称的 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"
}
#>
}
}
在评论区中需要有关功能的帮助。
将值包装在数组子表达式中 @()
并计算它有多少条目:
if(@($p).Count -gt 1){"Request group Id"}
注意:此答案补充
计算对象的数量return由命令编辑:
Mathias 的回答显示了一个 强大的、PowerShell v2 兼容的解决方案 基于 array sub-expression operator、
@()
.# @() 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
对象.[1] - 更一般地说,如果您需要确保命令输出 return 作为真正的 数组 编辑,但请注意它总是类型
[object[]]
;如果您需要 特定元素类型 ,请使用强制转换(例如[int[]]
),但请注意,您并不严格需要@(...)
;例如,
[int[]] (...)
会做 - 除非你想防止枚举集合输出为单个对象。
选择
(...).Count
,如果:- 只有一个命令的输出必须计算
- 对于将整个集合作为单个对象输出的命令,您想要计算此类集合的单个元素;也就是说,
(...)
强制枚举命令输出。[2] - 用于计算命令输出的元素已经存储在变量中 - 当然,您随后可以简单地省略
(...)
并使用$var.Count
警告:由于a longstanding bug(从 PowerShell Core 6.2.0 开始仍然存在),在 标量上访问 .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.
性能考虑:
如果一个命令的输出是直接计数,
(...)
和@(...)
执行的差不多:$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 VM(绝对时间并不重要,只是数字几乎相同):
Command Seconds ------- ------- (Write-Output $arr).Count 0.352 @(Write-Output $arr).Count 0.365
相比之下,对于大型集合 已经存储在变量中 ,
@(...)
引入了大量开销 ,因为集合被重新创建为(新)数组(如前所述,您可以$arr.Count
):$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 } }
示例输出;注意
@(...)
解决方案是如何慢 7 倍的:Command Seconds ------- ------- ($arr).Count 0.009 @($arr).Count 0.067
编码风格注意事项:
以下情况适用于 @(...)
和 (...)
在功能上等效(并且执行相同或性能次要)的情况,即当您 自由选择要使用的结构。
Mathias 推荐 @(...).Count
,在评论中指出:
There's another reason to explicitly wrap it in this context - conveying intent, i.e., "We don't know if
$p
is a scalar or not, hence this construct".
我投给 (...).Count
:
一旦您了解 PowerShell(v3 或更高版本)将标量视为按需计数为 1 的集合,您就可以自由利用这些知识,而无需在 语法:
编写代码时,这意味着 您不必担心给定的命令 情境 是否可能 return 标量而不是集合(这在 PowerShell 中很常见,其中使用 单个 输出对象捕获命令的输出按原样捕获该对象,而 2 个或更多 个输出对象导致 数组).
作为有益的副作用,代码变得更简洁(有时更快)。
示例:
# 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]
访问“其第一个元素”。
有关标量和集合的统一处理的更多信息,请参阅
[1] 例如,@(Write-Output -NoEnumerate 1, 2).Count
是 1
,因为 Write-Output
命令输出一个 单个 对象 -数组 1, 2
- _作为一个整体。因为只输出一个对象,@(...)
将该对象包装在一个数组中,导致 , (1, 2)
,即一个单元素数组,其第一个也是唯一一个元素本身就是一个数组。
[2] 例如,(Write-Output -NoEnumerate 1, 2).Count
是 2
,因为即使 Write-Output
命令将数组输出为单个对象,该数组也用作-是。也就是说,整个表达式等价于(1, 2).Count
。更一般地说,如果 (...)
中的命令仅输出 one 对象,则该对象按原样使用;如果它输出 多个 对象,它们将收集在常规 PowerShell 数组(类型 [object[]]
)中 - 这与通过 [=121 捕获命令输出时得到的行为相同=]变量赋值 ($captured = ...
)。