tags:

views:

330

answers:

1

Let me explain my question. I have a daily report about one PC's free space as in text file (sp.txt) like:

DateTime       FreeSpace(MB)
-----          -------------
03/01/2010     100.43


DateTime       FreeSpace(MB)
-----          -------------
03/02/2010     98.31

 ....

Then I need to use this file as input to generate a report with difference of free space between dates:

DateTime       FreeSpace(MB)  Change
-----          -------------  ------
03/01/2010     100.43
03/02/2010     98.31           2.12
 ....

Here are some codes I have to get above result without the additional "Change" calculation:

Get-Content "C:\report\sp.txt" `
| where {$_.trim().length -gt 0 -and -not ($_ -like "Date*") -and -not ($_ -like "---*")} `
| Select-Object @{Name='DateTime'; expression={[DateTime]::Parse($_.SubString(0, 10).Trim())}}, `
    @{Name='FreeSpace(MB)'; expression={$_.SubString(12, 12).Trim()}}, `
| Sort-Object DateTime `
| Select-Object DateTime, 'FreeSpace(MB)' |ft -AutoSize # how to add additional column Change to this Select-Object?

My understanding is that Select-Object will return a collection of objects. Here I create this collection from an input text file(parse each line into parts: datetime and freespace(MB)).

In order to calculate the difference between dates, I guess that I need to add additional calculated value to the result of the last Select-Object, or pipe the result to another Select-Object with the calculation as additional property or column. In order to do it, I need to get the previous row's FreeSpace value. Not sure if it is possible and how?

+1  A: 

I think this should work. I just unrolled it into a single loop where we keep track of the last value and use that to create the change property in the select expression. I also changed the parsing code slightly so you are not relying on hard coded substring lengths. It also helped make the select expressions easier to write and understand.

Get-Content "sp.txt" `
| where {$_.trim().length -gt 0 -and -not ($_ -like "Date*") -and -not ($_ -like "---*")} `
| %{ 
    $row = (-split $_ );  
    $obj = select-object -input $row -prop @{Name='DateTime'; expression={[DateTime]($row[0]);};} , `
                        @{Name='FreeSpace(MB)'; expression={[Double]($row[1]);} }, `
                        @{Name='Change'; expression={if($last){$row[1]-$last.'FreeSpace(MB)'}else{0}}}; 
    $last = $obj;
    $obj;
    } | sort DateTime | ft -autosize
zdan
quick comment here, to keep my question simple, I used datetime as date only. The actual value is date and time so there is one space among date, time and am/pm such as '03/01/2010 02:34:00 AM". Anyway, I'll give a try and to digest your solution. Thanks @zdan!
David.Chu.ca
how to format the change value to something like '0:N2' -f, ie 2 digits after decimal? Some values are like 0.18223233. I would like the change value to 0.18.
David.Chu.ca
To format the result as value with two digits, just use a temporary var such as $v to hold value in if and else, then return '{0:N2}' -f $v at the end of if else block.
David.Chu.ca