PowerShell:如果找不到字符串,则会出现意外错误

时间:2018-04-12 19:16:17

标签: powershell if-statement foreach

如果证书的到期时间是在当前日期的30天之内,我遇到了打印输出的脚本问题。但是我发现如果现在找到了expiry-epoch字符串,那么我会得到一条错误消息"无法索引到数组"这弄乱了我的输出。

请告诉我如何仅在包含expiry-epoch字符串

的文件上运行此脚本
$c = Get-Date (Get-Date).ToUniversalTime() -UFormat %s
$epochroundedtimes = [math]::Round($c)
$epochtimes = $epochroundedtimes + 2592000
Get-ChildItem -Path "C:\scripts\PALO" -File -Recurse | 
  ForEach-Object { $epochtimes } {
    $certexp = 
      [double] ($_ | Select-String -pattern "expiry-epoch (\d+)$").Matches.Groups[1].Value
    if ($certexp -le $epochtimes) {
      $_.FullName
    }
  }

2 个答案:

答案 0 :(得分:2)

试试这个:

$c = Get-Date (Get-Date).ToUniversalTime() -UFormat %s
$epochroundedtimes=[math]::Round($c)
$epochtimes=$epochroundedtimes + 2592000

Get-ChildItem -Path "C:\scripts\PALO" -File -Recurse | 
    ForEach-Object {
        $epochMatch = $_ | Select-String -pattern "expiry-epoch (\d+)$"

        if($epochMatch)
        {
            $certexp = ([double]($epochMatch.Matches.Groups[1].Value))

            if($certexp -le $epochtimes)
            {
                $_.FullName
            }
        }
}

编辑:根据评论添加简要说明

原始代码示例中的这一行生成了错误:

$certexp = 
      [double] ($_ | Select-String -pattern "expiry-epoch (\d+)$").Matches.Groups[1].Value

这是有问题的,因为如果目标文件不包含预期的字符串,Select-String不会产生输出,因此不需要MatchesGroup属性进行询问。将此行拆分为多个步骤,可以在尝试访问其属性之前检查是否有对象可以使用。也就是说,我们尝试字符串匹配:

$epochMatch = $_ | Select-String -pattern "expiry-epoch (\d+)$"

然后检查$epochMatch是否为实际对象:

if($epochMatch)

如果是,我们然后检索匹配的值:

$certexp = ([double]($epochMatch.Matches.Groups[1].Value))

答案 1 :(得分:0)

boxdog's helpful answer很好地解释了问题并提供了有效的解决方案。

让我补充一个简化的,更加PowerShell惯用的解决方案,在避免原始问题的同时提高效率:

Get-ChildItem -LiteralPath "C:\scripts\PALO" -File -Recurse | 
  Select-String -Pattern "expiry-epoch (\d+)$" | 
    ForEach-Object {
      # Extract the capture-group value from the [Microsoft.PowerShell.Commands.MatchInfo] 
      # instance that Select-String output.
      $certexp = [double] $_.Matches[0].Groups[1].Value
      if ($certexp -le $epochtimes) {
        # The .Path property of the [Microsoft.PowerShell.Commands.MatchInfo] 
        # instance contains the input file's full filename.
        $_.Path
      }
    }

直接将Get-ChildItem的输出汇总到Select-String意味着只有匹配才会通过管道传递,然后ForEach-Object调用可以安全地执行。