powershell - 如何使用 Powershell 将哈希表与另一个哈希表进行比较?
问题描述
我开始使用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])
}
}
现在如何比较这两个哈希图?
解决方案
JPBlanc建议在对该问题的评论中对记录进行分组,该Group-Object
cmdlet确实提供了一个概念上优雅的解决方案:
注意:假设一个给定的关键字只有一个条目,它始终是起始条目。
Select-String 'Starting thread:|Thread finished;' file.log |
Group-Object { (-split $_)[-1] } | Where-Object { $_.Count % 2 -eq 1 }
该
Select-String
调用使用正则表达式(正则表达式)仅提取感兴趣的行(线程开始,线程结束)该调用通过每行 ( ) 上最后一个 ( ) 空格分隔的标记 ( ) 对
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}
这可能不是您想要的格式,但鉴于输出是objects,这在 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 hours, 3 minutes, ...) 是一个[TimeSpan]
实例的字符串表示,它是减去两个时间点 ( [datetime]
instances) 的结果。
推荐阅读
- c++ - C++ 宏:对于每个 __VA_ARGS__?
- vuejs3 - vuex4中使用useStore的原因是什么
- powershell - PowerShell 模块错误 - 无法加载文件或程序集或其依赖项之一
- sql - 插入与另一个数据库同步的数据库
- javascript - JavaScript 对象 - Split() 方法 + '\n'
- android - 无法启动我的银行应用程序,它要求断开调试器
- python - 从提到的用户那里获取成员对象
- rust - 没有为 Type 实现 trait `std::marker::Copy`
- spring-boot - 从打开浏览器窗口中停止 Intellij 中的“运行 spring-boot”
- tampermonkey - Tampermonkey 在特定选项卡上运行脚本