我编写了一个PowerShell脚本来读取分隔的文件并逐行遍历它们。 该脚本将属性值保存到变量中,并在遇到字符串结尾时将这些值写入文件中。
假设没有安装.Net框架,是否有办法优化此脚本以提高速度?
class FastLapsSet(ModelViewSet):
queryset = Fastest_laps.objects.all()
serializer_class = ListSerializer
class DriverSet(ModelViewSet):
queryset = Driver.objects.all()
serializer_class = DetailSerializer
答案 0 :(得分:0)
Get-Content .\a.txt
运行缓慢,请用速度更快的[system.io.file]::ReadAllLines('c:\full\path\to\file\a.txt')
替换。
摆脱整个第一个循环,根本不回显有多少工作。如果必须这样做,则将循环推入堆栈,并使用$jobCount = ($LinesLoadedOnce -match '^end$').Count
并使用-match
而不是foreach
来进行循环/过滤。
与其每行文本文件多次调用Clear-Variable
并导致多次启动cmdlet的开销,不如调用一次并将其传递给要清除的名称数组,例如Clear-Variable -Name "insert_job", "job_type", "command", ..
。
代替使用>>storage.txt
每行打开和关闭txt文件一次,而是将输出收集到数组中,然后使用set-content
将其写入文件一次。
$results = foreach ($line in [system.io.file]::ReadAllLines('c:\full\path\to\file\a.txt'))
{
#code here
"'$insert_job','$job_type','$command', .."
}
$results | Set-Content -Path storage.txt
其余的内容更多地取决于文件的格式,文件的大小,如果要跳过的行,但可能会变成类似以下内容:
$headers = @(
'insert_job'
'job_type'
'command'
'machine'
'owner'
'permission'
'date_conditions'
'days_of_week'
'start_times'
'description'
'std_out_file'
'std_err_file'
'alarm_if_fail'
'end'
'box_name'
'condition'
'run_window'
'n_retrys'
'term_run_time'
'box_terminator'
'job_terminator'
'min_run_alarm'
'max_run_alarm'
'profile'
)
$headerRegex = "^($($headers -join '|'))\s*:\s*(.*?)\s*$"
$data = [ordered]@{}
foreach($h in $headers) { $data[$h] = $null }
$results = foreach ($line in [system.io.file]::ReadAllLines('c:\full\path\to\file\a.txt')) {
if ($line -match $headerRegex) {
$data[$matches[1]] = $matches[2]
}
elseif ($line -eq 'end') {
[PSCustomObject]$data
$data = [ordered]@{}
foreach($h in $headers) { $data[$h] = $null }
}
}
$results | Export-Csv storage.txt -NoTypeInformation
这将更多的工作投入正则表达式引擎,减少字符串处理和字符串插值,使用更少的变量和更少的cmdlet,避免所有切换和中断跳动,并且运行速度更快。
我没有测试过,因为我不知道您文件的内容。
答案 1 :(得分:0)
注释和TessellatingHeckler's answer中都有很好的指针,但是让我尝试将所有内容与速度改进一起使用-请参见代码中的注释。
rm storage.txt
$job_counter = 0
$att_counter = 0
# Read all lines into memory up front, using the .NET framework directly
# which is much faster than using Get-Content.
$allLines = [IO.File]::ReadAllLines("$PWD/a.txt")
# Count the lines that contain 'end' exactly to determine
# the number of jobs.
$job_counter = ($allLines -eq 'end').Count
"File has $job_counter jobs"
$job_counter = 0
# Initialize the hashtable whose entries will contain the values
# (rather than individual variables).
$values = [ordered] @{}
# Use a `switch` statement to process the lines, which is generally
# faster than a `foreach` loop.
switch ($allLines) {
'end' { # Use string equality (not regex matching), which is faster.
$job_counter++
"encountered job number $job_counter, it has $att_counter attributes"
# Write the values to
"'$($values.insert_job)','$($values.job_type)','$($values.command)','$($values.machine)','$($values.owner)','$($values.permission)','$($values.date_conditions)','$($values.days_of_week)','$($values.start_times)','$($values.description)','$($values.std_out_file)','$($values.std_err_file)','$($values.alarm_if_fail)','$($values.end)','$($values.box_name)','$($values.condition)','$($values.run_window)','$($values.n_retrys)','$($values.term_run_time)','$($values.box_terminator)','$($values.job_terminator)','$($values.min_run_alarm)','$($values.max_run_alarm)','$($values.profile)'" >>storage.txt
# Clear the values from the hashtable.
$values.Clear()
}
default {
# Split the line at hand into field name and value...
$fieldName, $value = $_ -split ':', 2, 'SimpleMatch'
# ... and add an entry for the pair to the hashtable.
$values.$fieldName = $value.trim()
$att_counter++
}
}
注意:上面的解决方案未验证输入文件中的字段名称;为此,需要额外的工作。