【问题标题】:Powershell sorting by date and timePowershell 按日期和时间排序
【发布时间】:2018-09-18 02:08:48
【问题描述】:

我想说(我是企鹅)我不是 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 { 

    }

【问题讨论】:

  • 日期和时间是否总是从相同的列号开始并占据相同的列位置数?
  • 它没有。出于这个原因,我使用代码在那些没有足够列的行中附加字段。 $AppendedLogLines 列在索引 (3,4) 处具有此日期和时间
  • 标准化以匹配"SMTPD" 行,然后将其写为 CSV 文件。然后,使用Import-CSV(链接上的文档)导入,并使用[DateTime]::ParseExact() 处理日期/时间字段(请参阅TechNetthis SO question
  • 记住,PowerShell 喜欢 objects,而不是 text。它提供了将文本转换为对象的方法,而无需手动进行繁重的解析,就像在 bashperl 中所做的那样。
  • 您上面的示例日志段是否显示了您可能遇到的所有行格式?

标签: powershell sorting datetime


【解决方案1】:

为了实现按时间戳排序,您不需要严格规范您的日志

Get-Content ./BHmailLog.txt | 
  Sort-Object { [datetime] ($_ -replace '^.*?"(\d{4}-\d{2}-\d{2} [^"]+).*', '$1') }

注意:
* 为简洁起见,我将提取时间戳的正则表达式缩短为仅匹配日期部分,但可以更严格。
* 如果有多个,这将按每行遇到的第一个时间戳排序。

方法:

  • 使用-replace 和正则表达式和捕获组从每个输入行中提取时间戳,
  • 通过强制转换将该字符串时间戳转换为[datetime] 实例,
    • 请注意,无论哪种文化有效,此转换都有效,因为 PowerShell 在从字符串转换/解析时尽可能使用 invariant 文化 - 并且您的时间戳采用不变文化可识别的格式。
  • 通过计算属性 ({ ... }) 使 Sort-Object 执行正确的时间排序。

请注意,即使您已首先对日志进行规范化,您也可以使用上述方法,但如果您随后更喜欢按字段索引定位时间戳:

$AppendedLogLines | Sort-Object { [datetime] ((-split $_)[3,4] -join ' ' -replace '"') }

虽然这在概念上可能更清晰、更容易理解,但我不确定哪种方法效果更好。

【讨论】:

    【解决方案2】:

    相当大的挑战.. 我不能为此编写代码,但我可以提供一些建议.. 使用空格作为分隔符分割每一行.. 然后你将不得不查看每个元素(或者只是第三或第四个)并查看它是否与日期/时间模式匹配。如果是这样,瞧;有您的搜索元素.. 将其作为键放入散列中,将整行作为数据。然后对你的哈希表进行排序。我就是这样处理它的。

    【讨论】:

    • 这样做的缺点是空间分割会破坏日期/时间字符串,PowerShell 可以获取整个字符串并将其转换为日期/时间对象。我会更倾向于按照我在 cmets 中的建议进行 - 标准化并导出为 CSV,然后导入并处理生成的对象。它的开销可能略高,但最终为您提供了更大的处理灵活性,特别是因为您可以对日期/时间对象进行数学运算,并对它们进行排序,而不必担心它们的区域设置相关的输入或输出格式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 1970-01-01
    • 2012-08-16
    • 2019-07-21
    • 2016-08-09
    • 2012-12-03
    • 1970-01-01
    相关资源
    最近更新 更多