Советы по эффективности сценариев Powershell - PullRequest
0 голосов
/ 13 февраля 2020

я впервые пишу здесь, но я долгое время скрывался, когда мне нужна помощь с кодом.

Я довольно новичок в Powershell, и, как и большинство людей, которых я изучал, Я сам пытаюсь кодировать каждый раз, когда могу, так что большая часть того, что я делаю, уродлива, но это работает, я хотел бы попросить совета по поводу сценария, который я недавно написал, что на данный момент у этого поста 15 часов и почти 50 % того, что он должен сделать, очевидно, что-то не так, но я недостаточно осведомлен, чтобы указать, что это такое, и любая помощь будет принята с благодарностью.

Итак, у меня есть телефония .csv со скомпилированными данными из январь 2020 года и несколько дней февраля, каждая строка имеет дату и время, потраченное на каждый статус, так как кто-то использует разный статус в течение дня, когда файл имеет одну строку для каждого статуса, мой сценарий должен go просмотреть файл, найти минимальная дата, а затем начните сохранять в новых файлах все данные за один и тот же день, поэтому я закончу одним файлом для 01-01-2020, 02-01-2020 и так далее, b но у него есть 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 = '' 

Большое спасибо за вашу помощь

1 Ответ

0 голосов
/ 13 февраля 2020

Первый l oop не имеет особого смысла. Он просматривает содержимое CSV и преобразует дату каждой строки в различные форматы. После этого $go никогда не используется.

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

Позже делается попытка вычислить значение из неинициализированной переменной. $today никогда не определяется.

$start = $DateString - $today

Похоже, однако, что вы хотите вычислить, в днях, сколько лет старшей записи.

Тогда есть все oop это считается от отрицательных дней до нуля. Во время каждой итерации ищется весь CSV:

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

Если 30 дней и 15 000 строк, то 30 * 15000 = 450 000 итераций. Это имеет сложность O (n ^ 2), что означает, что время выполнения будет go высоко в небе даже для относительно небольшого числа дней и строк.

Следующая часть состоит в том, что тот же массив обрабатывается снова:

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

Ну, условия поиска точно такие же, но теперь результаты отправляются в файл. Это побочный эффект удвоения вашей работы. Тем не менее, O (2n ^ 2) => O (n ^ 2), поэтому, по крайней мере, время выполнения не увеличивается в кубических c или хуже.

Что касается того, как это исправить, есть несколько вещей. Если вы сортируете CSV на основе даты, он может быть обработан впоследствии всего за один прогон.

$at = $at | sort -Property datefull

Затем повторите каждую строку. Поскольку строки расположены в порядке возрастания, первый является самым старым. Для каждой строки проверьте, изменилась ли дата. Если нет, добавьте его в буфер. Если он есть, сохраните старый буфер и создайте новый.

Образец не преобразует имена файлов в формате yyyyMMdd, и предполагает, что есть только два столбца foo и datefull, например,

$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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...