【问题标题】:Get all unique substrings from array in Powershell从Powershell中的数组中获取所有唯一的子字符串
【发布时间】:2015-09-15 22:07:16
【问题描述】:

我从日志中收集了一组字符串,我试图将其解析为唯一条目:

function Scan ($path, $logPaths, $pattern) 
{
$logPaths | % `
{ 
    $file = $_.FullName
    Write-Host "`n[$file]"
    Get-Content $file | Select-String -Pattern $pattern -CaseSensitive - AllMatches | % `
    {   
        $regexDateTime = New-Object System.Text.RegularExpressions.Regex "((?:\d{4})-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}(,\d{3})?)"
        $matchDate = $regexDateTime.match($_)
        if($matchDate.success)              
        {
            $loglinedate = [System.DateTime]::ParseExact($matchDate, "yyyy-MM-dd HH:mm:ss,FFF", [System.Globalization.CultureInfo]::InvariantCulture)
            if ($loglinedate -gt $laterThan)
            {                   
                $date = $($_.toString().TrimStart() -split ']')[0]
                $message = $($_.toString().TrimStart() -split ']')[1]
                $messageArr += ,$date,$message  
            }                                           
        }
    }
    $messageArr | sort $message -Unique | foreach { Write-Host -f Green $date$message}
}
}

所以对于这个输入:


2015-09-04 07:50:06 [20] WARN Core.Ports.Services.ReferenceDataCheckers.SharedCheckers.DocumentLibraryMustExistService - 找不到 DocumentLibrary 3。

2015-09-04 07:50:06 [20] WARN Core.Ports.Services.ReferenceDataCheckers.SharedCheckers.DocumentLibraryMustExistService - 找不到 DocumentLibrary 3。

2015-09-04 07:50:16 [20] WARN Brighter - 消息 abc123 已被消费者标记为已过时,因为实体在消费者端具有更高版本。


只应返回后两个条目

我在过滤掉重复的 $message 时遇到了麻烦:目前所有条目都被返回(sort -Unique 的行为不像我预期的那样)。我还需要针对过滤后的 $message 返回正确的 $date。

我很困惑,有人可以帮忙吗?

【问题讨论】:

  • 我无法理解您使用的文本格式,因为我看不到输入。作为一般建议,请尝试通过管道连接到 Group-Object。它会自动对唯一值进行分组,并为您提供每个值的总数。

标签: arrays sorting powershell split unique


【解决方案1】:

我们可以做任何你想做的事,但首先让我们稍微备份一下,以帮助我们做得更好。现在你有一个数组数组,一般来说很难处理。如果您有一个对象数组,并且这些对象具有诸如日期和消息之类的属性,那会更好。让我们从那里开始。

        if ($loglinedate -gt $laterThan)
        {                   
            $date = $($_.toString().TrimStart() -split ']')[0]
            $message = $($_.toString().TrimStart() -split ']')[1]
            $messageArr += ,$date,$message  
        }                                           

会变成……

        if ($loglinedate -gt $laterThan)
        {                   
            [Array]$messageArr += [PSCustomObject]@{
                'date' = $($_.toString().TrimStart() -split ']')[0]
                'message' = $($_.toString().TrimStart() -split ']')[1]
            }
        }                                           

这会产生一个对象数组,每个对象都有两个属性,日期和消息。这将更容易使用。

如果您只想要使用Group-Object 命令轻松完成的任何消息的最新版本:

$FilteredArr = $messageArr | Group Message | ForEach{$_.Group|sort Date|Select -Last 1}

然后,如果您想将其显示在屏幕上,您可以这样做:

$Filtered|ForEach{Write-Host -f Green ("{0}`t{1}" -f $_.Date, $_.Message)}

【讨论】:

  • 效果很好,解释也很好。非常感谢。
【解决方案2】:

我的看法(未经测试):

function Scan ($path, $logPaths, $pattern) 
{

$regex = '(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})\s(.+)'
$ht = @{}

$logPaths | % `
   { 
     $file = $_.FullName
     Write-Host "`n[$file]"
     Get-Content $file | Select-String -Pattern $pattern -CaseSensitive -AllMatches | % `
      {   
       if ($_.line -match $regex -and $ht[$matches[2]] -gt $matches[1])
         { $ht[$matches[2]] = $matches[1] }
      }  
    $ht.GetEnumerator() |
     sort Value |
     foreach { Write-Host -f Green "$($_.Value)$($_.Name)" }
  }
}

这会在时间戳处拆分文件,并将部分加载到哈希表中,使用错误消息作为键,时间戳作为数据(这将对流中的消息进行重复数据删除)。

时间戳已经是字符串可排序格式(yyyy-MM-dd HH:mm:ss),所以真的没有必要将它们转换为 [datetime] 来查找最新的。只需进行直接字符串比较,如果传入的时间戳大于该消息的现有值,则将现有值替换为新值。

完成后,您应该有一个哈希表,其中包含找到的每条唯一消息的键,其值是为该消息找到的最新时间戳。

【讨论】:

  • 感谢您的回复。我应该发布完整的代码,日期解析是为了使用 $laterthan 变量只选择日期 -gt 而不是 $laterthan。我尝试了下面的代码并得到'索引操作失败;数组索引评估为空。'获取内容 $file | Select-String -Pattern $pattern -CaseSensitive -AllMatches | % ` { if ($_.line -match '].*' -and $ht[$matches[2]] -gt $matches[1]) { $ht[$matches[2]] = $matches[1 ] } }
  • 它不适用于 if ($_.line -match '].*。您需要使用带有捕获组的正则表达式(如示例中的那个)。就日期而言解析,只需将 $laterthan 设置为相同日期格式的字符串值 - 例如 '2015-01-01 00:00:00' 就可以了。你自己试试吧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-29
  • 1970-01-01
  • 1970-01-01
  • 2016-03-18
  • 1970-01-01
  • 1970-01-01
  • 2019-07-18
相关资源
最近更新 更多