【问题标题】:Return boolean from string search从字符串搜索返回布尔值
【发布时间】:2021-10-22 05:48:01
【问题描述】:

我正在尝试通过搜索 Get-ComplianceSearch 的“已完成”输出来返回 TRUE。我下面的代码是一个简单的等待循环。但我认为我没有正确返回值,因为循环永远不会结束。我对 PowerShell 相当陌生。请协助或指导。

我使用的是 Powershell Core 7.1。没有错误,但 Search-String 条件永远不会返回 TRUE。

    try {
        $timer = [Diagnostics.Stopwatch]::StartNew()
        while (($timer.Elapsed.TotalSeconds -lt $Timeout) -and (-not (Get-ComplianceSearch - 
Identity $searchName | Select-String 'Completed' -SimpleMatch -Quiet))) {
        Start-Sleep -Seconds $RetryInterval
        $totalSecs = [math]::Round($timer.Elapsed.TotalSeconds, 0)
        Write-Verbose -Message "Still waiting for action to complete after [$totalSecs] 
seconds..."
        }
    $timer.Stop()
    if ($timer.Elapsed.TotalSeconds -gt $Timeout) {
        throw 'Action did not complete before timeout period.'
    } else {
        Write-Verbose -Message 'Action completed before timeout period.'
    }
} catch {
    Write-Error -Message $_.Exception.Message
}

(这是 Get-ComplianceSearch 命令的预期输出)

【问题讨论】:

    标签: powershell where-clause select-string


    【解决方案1】:

    好的,你不想在这里使用Select-String(虽然你可以,请参阅@mklement0 的helpful answer,查看对象属性通常是首选)。那是返回一个对象,您想检查Status 属性中的"Completed"。对-not 子表达式进行以下更改:

    (-not (Get-ComplianceSearch -Identity $searchName | Where-Object {
      $_.Status -eq 'Completed'
    }))
    

    以上内容可以放在一行,但为了便于阅读,我将其分开。


    基本上,Select-String 在字符串中查找内容。但是,如果您正在寻找对象属性的特定值,则可以使用Where-Object 来测试条件并返回与该条件匹配的任何对象。在这种情况下,我们希望返回任何具有'Completed'Status 的对象,因此我们可以在if 语句中否定它。


    您(或其他人)可能想知道这是如何工作的,因为 Where-Object 返回匹配的对象,而不是布尔值。答案是“真实”。 PowerShell 对象是“真实的”,这意味着任何东西都可以被评估为 [bool]

    在大多数情况下,以下值的计算结果为 $false。在依赖“真实”价值观时,我列出了一些需要注意的问题:

    • 0 的数值
      • 0 的字符串值计算为$true
    • 空数组
    • 空字符串
      • 仅包含空格的字符串或仅由不可打印字符组成的字符串的计算结果为 $true
    • $false
      • False 的字符串值计算为$true

    大多数其他内容都将评估为$true。这也是为什么在检查变量是否为$null 时比较运算符在语法上是可选的。虽然有时显式值检查是个好主意,因为比较运算符会比较实际值,而不仅仅是变量“is”还是“isn't”。

    这如何应用于上面的表达式呢?简单的。 if 语句,始终将条件表达式视为 [bool],无需转换。此外,逻辑运算符和条件运算符也意味着布尔比较。例如,$var = $obj$obj 分配给$var,但
    $var = $obj -eq $obj2$var = $obj -and $obj2 将分配$true$false


    所以知道上面的,如果Where-Object什么都不返回,那就是$false。如果它返回一个有形的对象,它是$true

    【讨论】:

      【解决方案2】:

      Bender the Greatest's helpful answer 显示了使用Select-String更好的替代方法,因为查询特定属性的基于 OO 的过滤总是比搜索字符串表示更可靠。 p>

      也就是说,对于快速而肮脏的交互式搜索,能够通过命令的格式化显示输出进行搜索会很方便,不幸的是,Select-String 默认情况下这样做


      至于你尝试了什么

      要使您的Select-String 工作,您需要在Select-String 调用之前插入Out-String -Stream,以确保通过管道发送for-display 表示,一行一行。

      # `oss` can be used in lieu of `Out-String -Stream` in PSv5+.
      # `sls` can be used in lieu of `Select-String`.
      Get-ComplianceSearch | Out-String -Stream | Select-String 'Completed' -SimpleMatch -Quiet
      

      注意:

      • 如果您想搜索显示表示默认的表示以外,您可以在Out-String -Stream 段之前插入Format-* cmdlet 调用;例如,
        Get-Item / | Format-List * | Out-String -Stream | Select-String ... 将搜索由Get-Item 输出的对象的所有属性的列表 表示。

      也许令人惊讶的是,Select-String 确实搜索输入对象的 for-display 表示,正如您在 console,使用 PowerShell 的 display-formatting system 提供的丰富格式。

      相反,它执行简单的.ToString()stringification,其结果通常没有帮助,不能依赖于包含属性的值 . (例如,
      @{ foo = 'bar' } | Select-String foo 是否按预期工作;它等同于
      @{ foo = 'bar' }.ToString() | Select-String foo,因此等同于
      'System.Collections.Hashtable' | Select-String foo

      可以说,Select-String 应该始终默认搜索输入对象的格式化字符串表示形式

      • PowerShell 版本 5 及更高版本(两个版本)附带 oss 便利函数,它是 Out-String -Stream 的包装器,这一事实证明了这种行为的需求。

      • GitHub issue #10726 要求将Select-String 的当前行为更改为搜索显示字符串表示默认情况下

      【讨论】:

      • 感谢您的澄清。非常有用。
      • 我还学到了一些东西,我从来不知道如何或什么定义了控制台中某些 PowerShell 对象的默认显示。 for-display 似乎是这里的关键词。也从未想过将对象通过管道传输到 Out-String -Stream 以搜索相同的视觉表示
      • 很高兴听到这个消息,@Ccorock;另请参阅我的更新。
      • 不错。我希望他们也能将Select-String 别名为ss 开箱即用,但我想我可以明白他们为什么会远离那个。
      • @BendertheGreatest :) sls 是内置别名,但请注意它的名称格式不规则:因为 scSelect-* 命令的官方别名前缀,它应该是scs.
      猜你喜欢
      • 2014-06-28
      • 1970-01-01
      • 2018-05-03
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 2018-10-10
      • 2014-07-26
      • 2017-12-20
      相关资源
      最近更新 更多