powershell - 如何使用 Powershell 将哈希表与另一个哈希表进行比较?

标签 powershell hashmap hashtable

我正在开始使用 powershell,但我现在的知识还很贫乏。 我有这个 .log 文件,如下所示:

18.7.2017 12:59:15  Starting thread: KEYWORD1
18.7.2017 12:59:33  Thread finished; ... KEYWORD1
18.7.2017 13:32:19  Starting thread: KEYWORD2
18.7.2017 13:34:8  Thread finished;... KEYWORD2

我现在想知道,是否每个启动的线程也都已完成。 如果有未完成的线程,我想将时间戳与当前时间进行比较。

我认为哈希表可以解决问题,这就是我想到的:

foreach($line in Get-Content $sourceDirectory)
{
    if($line -like "*Starting thread*")
    {
        $arrStart = $line -split ' '
        $startThreads=$arrStart[$arrStart.Length-1]
        $hashmap1 = @{$arrEnd[$arrEnd.Length-1] = $arrEnd[1]}
    }

    if($line -like "*Thread finished*")
    {
        $arrEnd = $line -split ' '
        $hashmap2 = @{$arrEnd[$arrEnd.Length-1] = $arrEnd[1]}
        $endThreads=($arrEnd[1]+" "+$arrEnd[$arrEnd.Length-1])
    }
}

现在如何比较这两个 HashMap ?

最佳答案

JPBlanc建议对问题评论中的记录进行分组,并且 the Group-Object cmdlet确实提供了一个概念上优雅的解决方案:

注意:假设如果给定关键字只有一个条目,则它始终是起始条目。

Select-String 'Starting thread:|Thread finished;' file.log | 
  Group-Object { (-split $_)[-1] } | Where-Object { $_.Count % 2 -eq 1 }
  • Select-String call 使用 regex(正则表达式)仅提取感兴趣的行(线程开始、线程结束)

  • Group-Object 调用按最后一个 ([-1]) 空格分隔的标记 (-split .. .) 每行 ($_),即关键字。

  • Where-Object然后仅返回那些具有奇数个条目的结果,即那些不成对的条目,代表已启动但未完成的线程。

这会产生如下内容:

Count Name          Group
----- ----          -----
    1 KEYWORD3      {/Users/jdoe/file.log:5:28.8.2018 08:59:16  Starting thread: KEYWORD3}

这可能不是您想要的格式,但鉴于输出是对象(正如 PowerShell 中的典型情况),您可以轻松地以编程方式根据您的喜好处理它们。

从技术上讲,上述命令输出 [Microsoft.PowerShell.Commands.GroupInfo]在本例中 .Group 属性包含 [Microsoft.PowerShell.Commands.MatchInfo] 的实例实例,由 Select-String 输出。

<小时/>

以下代码扩展了上面的代码以生成自定义输出,报告自每个未完成的线程启动以来已经过去了多少时间:

$now = Get-Date
Select-String 'Starting thread:|Thread finished;' file.log  | 
  Group-Object { (-split $_)[-1] } | Where-Object { $_.Count % 2 -eq 1 } | ForEach-Object {
    foreach ($matchInfo in $_.Group) { # loop over started-only lines
      $tokens = -split $matchInfo.Line # split into tokens by whitespace
      $date, $time = $tokens[0..1]     # extract date and time (first 2 tokens)
      $keyword = $tokens[-1]           # extract keyword (last token)
      # Parse date+time into a [datetime] instance.
      # Note: Depending on the current culture, [datetime]::Parse("$date $time") may do.
      $start = [datetime]::ParseExact("$date $time", 'd\.M\.yyyy HH:mm:ss', [cultureinfo]::InvariantCulture)
      # Custom output string containing how long ago the thread was started:
      "Thread $keyword hasn't finished yet; time elapsed since it started: " +
        ($now - $start).ToString('g')
    }
  }

这会产生如下内容:

Thread KEYWORD3 hasn't finished yet; time elapsed since it started: 2:03:35.347563

2:03:35.347563(2 小时,3 分钟,...)是 [TimeSpan] 的字符串表示形式实例是减去两个时间点([datetime]实例)的结果。

关于powershell - 如何使用 Powershell 将哈希表与另一个哈希表进行比较?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52058355/

相关文章:

java - 如何打印存储在 Tree 中的所有单词,其中 trie 已在 Java 中使用 Hashmap 实现?

arrays - Powershell:如何使用数组或哈希表作为内联查找

windows - 在后台运行的启动脚本

java - 如何在 Java 中将 hashmap 的值转换为 String

powershell - 数组中的Get-ScheduledTask状态

java - 没有集合库的哈希表

java - 将 Java LinkedHashMap 转换为 C++ std::map

c - 如何遍历C中的哈希表

datetime - 我可以控制 cmdlet 显示的日期时间格式吗?

Powershell 命令在 Visual Studio 的构建事件中不起作用