powershell - Powershell 按日期和时间排序
问题描述
我想说(我是一只企鹅)我不是 Windows 或 Powershell 人,但这不应该阻止我帮助我们的 Windows 团队。
我需要合并两个日志并按日期和时间对它们进行排序。我认为将它们组合起来应该很简单,但是按日期和时间排序似乎让我有点失望。
我正在使用的日志没有相同数量的列,因此我对日志进行了某种规范化,以尝试按日期和时间的 logline[3,4] 进行排序。
"SMTPD" 4416 2476943 "2018-09-11 23:53:37.410" "1.1.1.1" "SENT: 221 goodbye"
"TCPIP" 4308 "2018-09-11 23:59:47.255" "TCP - 1.1.1.2 connected to 1.1.1.1:25."
"SMTPD" 4308 2476952 "2018-09-11 23:22:47.255" "1.1.1.1" "SENT: 220 mx9.bobdestroyer.com ESMTP"
"SMTPD" 4416 2476952 "2018-09-11 23:35:47.255" "1.2.3.4" "RECEIVED: EHLO smtp-cow-666"
"SMTPD" 4416 2476952 "2018-09-11 23:22:47.255" "1.1.1.1" "SENT: 250-mx5.bobthedestroyer.com[nl]250-SIZE 20480000[nl]250-AUTH LOGIN[nl]250 HELP"
"SMTPD" 4232 2476952 "2018-09-11 23:53:47.255" "1.1.1.1" "RECEIVED: MAIL FROM:<bobtheBuilder@builders.com>"
"SMTPD" 4232 2476952 "2018-09-11 23:59:47.255" "1.1.1.1" "SENT: 250 OK"
"SMTPD" 4416 2476952 "2018-09-11 23:11:47.270" "1.1.1.1" "RECEIVED: RCPT TO:<bobtheBuilder@builders.com>"
"SMTPD" 4416 2476952 "2018-09-11 23:22:47.270" "1.1.1.1" "SENT: 250 OK"
"SMTPD" 4308 2476952 "2018-09-11 23:55:47.270" "1.1.1.1" "RECEIVED: DATA"
"SMTPD" 4308 2476952 "2018-09-11 23:21:47.270" "1.1.1.1" "SENT: 354 OK, send."
"SMTPD" 4000 2476952 "2018-09-11 09:53:48.208" "1.1.1.1" "SENT: 250 Queued (0.768 seconds)"
"APPLICATION" 3100 "2018-09-11 11:53:48.208" "SMTPDeliverer - Message 2570349: Delivering message from bobtheBuilder@builders.com to bobtheDestroyers@Destroyerrs.com . File: C:\Program Files (x86)\servers\toomanysecrets\{49E08D79-C4A5-43F1-9435-9999999999}.eml"
"APPLICATION" 3100 "2018-09-11 12:12:48.208" "SMTPDeliverer - Message 2570349: Relaying to host bobtheBuilder@builders.com ."
这是我写的:
$Unclean_LogLines = Get-Content .\BHmailLog.txt
#$LogLines | %{"$($_.Split()[0,1,2,3,4,5,6,7,8,9,10,11,12,13 ])"}
$AppendedLogLines = [System.Collections.ArrayList]@()
#Attempts to normalise the log.... And even out the columns.So that I can grap $_[3,4] for each line.
#perhaps a simple foreach + regex would be better....
$Unclean_LogLines | foreach-object {
$firstcolumn = ($_ -split '\s+',4)[0]
if($firstcolumn -eq '"APPLICATION"'){
$_ = '"APPLICATION" ' + $_
$AppendedLogLines.Add($_ + "`n")
}
elseif($firstcolumn -eq '"TCPIP"'){
$_ = '"TCPIP" ' + $_
$AppendedLogLines.Add($_ + "`n") # minor problem here. I am not 100% normalising the log... I should make _$[2] = 4248 or something.
}
else{
$AppendedLogLines.Add($_ + "`n")
}
}
"FINISHED NORMALISING!! "
$AppendedLogLines| foreach-object {
$timestamp,$null = %{"$($_.Split()[3,4])"}
$timestamp = $timestamp.Replace('"','') # remove the last qoate....
$_ |sort-object -property {
}
解决方案
为了实现按时间戳排序,您不需要严格规范您的日志:
Get-Content ./BHmailLog.txt |
Sort-Object { [datetime] ($_ -replace '^.*?"(\d{4}-\d{2}-\d{2} [^"]+).*', '$1') }
注意:
* 为简洁起见,我将提取时间戳的正则表达式缩短为仅匹配日期部分,但可以更严格。
* 如果有多个,这将按每行遇到的第一个时间戳排序。
该方法:
- 使用
-replace
正则表达式和捕获组从每个输入行中提取时间戳, - 通过强制转换将该字符串时间戳转换为
[datetime]
实例,- 请注意,无论哪种文化有效,此转换都有效,因为 PowerShell在可能的情况下从字符串转换/解析时使用不变文化 - 并且您的时间戳采用不变文化识别的格式。
- 它通过计算属性 (
{ ... }
)Sort-Object
执行正确的时间排序。
请注意,即使您首先对日志进行了规范化,也可以使用上述方法,但如果您随后更愿意通过字段索引来定位时间戳:
$AppendedLogLines | Sort-Object { [datetime] ((-split $_)[3,4] -join ' ' -replace '"') }
虽然这在概念上可能更清晰,更容易理解,但我不确定哪种方法效果更好。
推荐阅读
- python - 如何通过 Docker 使用 Buildozer 构建 .aab?
- javascript - 使用箭头函数的斐波那契数列
- python - SELENIUM PYTHON 我的脚本卡在 driver.get(url) 行
- python - 无法从flower.command 导入名称 FlowerCommand
- google-sheets - 谷歌表格中是否有一个公式可以从众多选项中选择一个分配给单元格?
- reactjs - 如何将 useState 数据传递给另一个 .tsx 文件?
- vue.js - 如何在 vee-validate 中使用 vue3 输入组件?
- angular - 阻止 Angular 12 用
- sql - 我可以在TDengine中以restful风格执行多个SQL语句吗?
- python - 无法使用 pandas.read_html() 将多个表中的内容添加到 csv 文件