簡體   English   中英

Powershell 腳本效率建議

[英]Powershell script efficiency advice

這是我第一次在這里發帖,但每次我需要一些代碼幫助時,我都潛伏了很長時間。

我對 Powershell 還是很陌生,而且正如我一直在自己學習的大多數人一樣,我每次都嘗試編寫代碼,所以我所做的大部分事情都很丑陋,但它有效,我想就我的腳本尋求建議最近寫道,目前這篇文章已經運行了 15 小時,幾乎完成了它必須做的 50%,顯然有問題,但我知識不足,無法指出它是什么,任何幫助將不勝感激。

因此,我有一個電話 .csv 文件,其中包含 2020 年 1 月和 2 月某些天的編譯數據,每一行都有在每個狀態上花費的日期和時間,因為有人在一天內使用不同的狀態,文件為每個狀態有一行,我的腳本應該遍歷文件,找到最小日期,然后開始在新文件中保存同一天的所有數據,所以我將以 01-01-2020、02-01-2020 等的一個文件結束打開,但它運行了 15 小時,它仍然是 1/22。

我用於日期的列稱為“DateFull”,這是腳本

write-host "opening file" 
$AT= import-csv “C:\Users\xxxxxx\Desktop\SignOnOff_20200101_20200204.csv” 
write-host "parsing and sorting file" 
$go= $AT| ForEach-Object {
        $_.DateFull= (Get-Date $_.DateFull).ToString("M/d/yyyy")
        $_
        }

Write-Host "prep day"
$min = $AT | Measure-Object -Property Datefull  -Minimum  

Write-Host $min
$dateString =  [datetime] $min.Minimum
Write-host $datestring

write-host "Setup dates"
$start = $DateString - $today
$start = $start.Days

For ($i=$start; $i -lt 0; $i++)  {
$date = get-date
$loaddate = $date.AddDays($i) 
$DateStr = $loadDate.ToString("M/d/yyyy")
$now = Get-Date -Format HH:mm:ss
write-host $datestr " " $now

#Install-Module ImportExcel #optional import if you dont have the module already
$Check = $at | where {$_.'DateFull' -eq $datestr} 
write-host $check.count
if ($check.count -eq 0 ){}
else {$AT | where {$_.'DateFull' -eq $datestr} | Export-Csv "C:\Users\xxxxx\Desktop\signonoff\SignOnOff_$(get-date (get-date).addDays($i) -f yyyyMMdd).csv" -NoTypeInformation}
}

$at = '' 

非常感謝你的幫助

第一個循環沒有多大意義。 它遍歷 CSV 內容並將每一行的日期轉換為不同的格式。 之后, $go不再使用。

$go= $AT| ForEach-Object {
        $_.DateFull= (Get-Date $_.DateFull).ToString("M/d/yyyy")
        $_
        }

后來,嘗試從未初始化的變量計算值。 $today從未定義過。

$start = $DateString - $today

但是,看起來您想以天為單位計算最老記錄的年齡。

然后有一個循環,從負天數到零。 在每次迭代期間,搜索整個 CSV 文件:

$Check = $at | where {$_.'DateFull' -eq $datestr} 

如果有 30 天和 15 000 行,則有 30*15000 = 450 000 次迭代。 這具有 O(n^2) 的復雜性,這意味着即使在相對較少的天數和行數內,運行時也會飛得很高。

下一部分是再次處理同一個數組:

else {$AT | where {$_.'DateFull' -eq $datestr

嗯,搜索條件完全一樣,但現在結果被發送到一個文件。 這有一個副作用,使您的工作加倍。 盡管如此,O(2n^2) => O(n^2),所以至少運行時間不會以三次或更糟的方式增長。

至於如何解決這個問題,有幾件事。 如果您根據日期對 CSV 進行排序,則只需運行一次即可對其進行處理。

$at = $at | sort -Property datefull

然后,迭代每一行。 由於行按升序排列,第一個是最舊的。 對於每一行,檢查日期是否已更改。 如果沒有,請將其添加到緩沖區。 如果有,保存舊緩沖區並創建一個新緩沖區。

該示例不會以 yyyyMMdd 格式轉換文件名,並且它假設只有兩列foodatefull像這樣,

$sb = new-object text.stringbuilder
# What's the first date?
$current = $at[0]

# Loop through sorted data
for($i = 0; $i -lt $at.Count; ++$i) {

    # Are we on next date?
    if ($at[$i].DateFull -gt $current.datefull) {
        # Save the buffer
        $file = $("c:\temp\OnOff_{0}.csv" -f ($current.datefull -replace '/', '.') )
        set-content $file $sb.tostring()
        # Pick the current date
        $current = $at[$i]

        # Create new buffer and save data there
        $sb = new-object text.stringbuilder
        [void]$sb.AppendLine(("{0},{1}" -f $at[$i].foo, $at[$i].datefull))    
    } else {
        [void]$sb.AppendLine(("{0},{1}" -f $at[$i].foo, $at[$i].datefull))    
    }
}
# Save the final buffer
$file = $("c:\temp\OnOff_{0}.csv" -f ($current.datefull -replace '/', '.') )
set-content $file $sb.tostring()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM