从文件中提取文件名和数据

时间:2014-09-09 12:31:27

标签: powershell mschart

我在过去几个月内每小时都有一个日志文件,我想将数据导出到MS Charts。

我设法将数据输出,但是在图表的x轴上获取日期时出现问题。

日志文件的文件名包含日期,我尝试使用创建日期或上次写入时间。我最接近的是计算日志数然后除以24,但它生成的日期与数据不匹配。

有什么想法吗?

一切都按预期工作,但我不能让X轴显示正确的日期。理论上,它应该将6月11日计算为开始日期,结束日期是昨天的日期。 它从中读取的文件的格式是 HealthCheck 2014年9月10日星期三 - 05.00 AM.log

理想情况下,我想从文件名中获取日期。我不想依赖于文件写入时的计算,因为这很容易出错。

[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization")
$Farm = "XAccess"

#gets files from yesterday
$Date = Get-Date #-Uformat %x
$Date = ($Date).adddays(-1)
$Date = $Date.ToString("M/d/yyyy")
$files = get-childitem "c:\$Farm*.log" | Where{$_.LastWriteTime -lt $date}

$ActiveSessions = Select-String -path $files '(?<=^"*Total Active Sessions: )\d+(?=)'|

 ForEach-Object {$_.Matches[0].Value}


#Calculates numbers of days 
$datapoints = $ActiveSessions.count/24

#== Creates Chart ==#

# create chart object 
$Chart = New-object System.Windows.Forms.DataVisualization.Charting.Chart 
$Chart.Width = 1600
$Chart.Height = 800

# create a chartarea to draw on and add to chart 
$ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea 
$Chart.ChartAreas.Add($ChartArea) 
[void]$Chart.Series.Add("Data")
$Chart.ChartAreas["ChartArea1"].AxisX.Interval = 24
$Chart.ChartAreas["ChartArea1"].AxisX.LabelStyle.Angle = -40
$Chart.ChartAreas["ChartArea1"].AxisY.Interval = 5
$Chart.ChartAreas["ChartArea1"].AxisY.title = "Active Sessions"
$chart.Series.Add('ChartArea1')

# add a data point for each server 

foreach ($session in $ActiveSessions) 
{ 
$dp1 = new-object System.Windows.Forms.DataVisualization.Charting.DataPoint(0, $session) 
$dp1.AxisLabel = (get-date).adddays(-"$datapoints").tostring("ddd dd MMM")
$datapoints = $datapoints - 0.0416666666666667 
$Chart.Series["Data"].Points.Add($dp1)
} 


# set the title to the date and time 
$title = new-object System.Windows.Forms.DataVisualization.Charting.Title 
$Chart.Titles.Add( $title )
$Chart.Titles[0].Font = "Arial,13pt" 
$Chart.Titles[0].Text = "Year to Date sessions for $Farm" 

# save the chart to a file 
$Chart.SaveImage("C:\$Farm Farm.png","png")

2 个答案:

答案 0 :(得分:0)

好的,所以你想要文件中的日期。没问题,我们可以做到。让我们从最好的方式开始...我们有选择(像往常一样)可供选择。等等,我领先于自己。我们在哪里定义它?好吧,我能想到的最简单的地方是你正在循环查看相关文件并获取其他数据的任何地方,这样我们就可以保持一切正确关联。因此,看起来您指定的行$ActiveSessions将是我们最好的选择。

现在,回到如何获取日期。我们可以使用SubString方法,但是当我们为文本定义了格式时,这对我来说似乎很麻烦。就个人而言,我宁愿做正则表达式匹配。所以我在文件名中看到的是三个字母的日缩写,然后是1-2个数字日,一个三个字母的月份和一个四位数的年份。之后有一个连字符,两位数小时,句号,两位数分钟,以及AM / PM指示符。

因此,就[datetime]格式而言,ddd d MMM yyyy - hh.mm tt就是这样。我们会回过头来看看。如何提取日期?哦,对了,一个正则表达式。这是我如何得到的:

([regex]"\w{3} \d{1,2} \w{3} \d{4} - \d{2}\.\d{2} (?:AM|PM)").matches($_.Filename).value

将模式声明为正则表达式对象,然后使用它的Matches()方法,并获取匹配的值。所以我们有了约会,现在实际上可以使用它。这是我们回到DateTime格式的地方。我们可以使用[DateTime] :: ParseExact()方法来获取日期时间,即使是奇怪的格式也是如此。现在我们将在ForEach循环中获取它,并从Select-String为循环提供的对象的FileName属性中提取日期。这是它的样子:

[datetime]::ParseExact(([regex]"\w{3} \d{1,2} \w{3} \d{4} - \d{2}\.\d{2} (?:AM|PM)").matches($_.Filename).value,"ddd d MMM yyyy - hh.mm tt",$null)

好的,这实际上为我们提供了一个很好的可用日期时间对象。因此ForEach循环已经吐出活动会话,$ ActiveSessions是一个字符串数组。让我们改变一点,使它成为一个对象数组,每个对象现在都有两个属性,Sessions和Date。因此ForEach循环的内部必须使用这些属性创建一个对象。最简单的方法(使用PowerShell v3或更高版本,如果您运行旧版本的PowerShell并需要我,我将向您展示困难的方法):

[PSCustomObject][Ordered]@{
    'Sessions'=$_.Matches[0].Value
    'Date'=[datetime]::ParseExact(([regex]"\w{3} \d{1,2} \w{3} \d{4} - \d{2}\.\d{2} (?:AM|PM)").matches($_.Filename).value,"ddd d MMM yyyy - hh.mm tt",$null)
}

这使整个$ActiveSessions =行看起来像:

$ActiveSessions = Select-String -path $files '(?<=^"*Total Active Sessions: )\d+(?=)'|
 ForEach-Object {[PSCustomObject][Ordered]@{
    'Sessions'=$_.Matches[0].Value
    'Date'=[datetime]::ParseExact(([regex]"\w{3} \d{1,2} \w{3} \d{4} - \d{2}\.\d{2} (?:AM|PM)").matches($_.Filename).value,"ddd d MMM yyyy - hh.mm tt",$null)
    }
}

唯一离开的是改变引用变量的位置:

foreach ($session in $ActiveSessions) 
{ 
$dp1 = new-object System.Windows.Forms.DataVisualization.Charting.DataPoint(0, $session.session) 
$dp1.AxisLabel = $Session.Date.tostring("ddd dd MMM")
$Chart.Series["Data"].Points.Add($dp1)
} 

那应该为你做。

答案 1 :(得分:0)

我尝试使用正则表达式但无法通过我提到的错误。

所以经过一番研究后,我决定将文件的创建日期和我需要的数据导出到CSV文件中,然后从中创建图表。所以这是我用来将数据输入csv的代码:

$files = get-childitem "c:\$farm*.log" | sort CreationTime    
Foreach ($file in $files)
{
    $FileCreation = $file.CreationTime.Date.ToString('ddd dd MMM yyyy')
    $ActiveSessions = Select-String -path $file '(?<=^"*Total Active Sessions: )\d+(?=)' | ForEach-Object {$_.Matches[0].Value}
   Add-Content d:\licInUse.csv "$FileCreation,$ActiveSessions"
}
    # processing the Data
    $Processes = Import-Csv -path d:\licInUse.csv -Delimiter ',' -Header "Date","Count"
    $DateNames = @(foreach($Date in $Processes){$Date.Date}) 
    $SessionCount = @(foreach($Date in $Processes){$Date.Count})

然后使用以下内容绘制数据

$Chart.Series["Data"].Points.DataBindXY($DateNames, $SessionCount)