Powershell: улучшение преобразования файла LDIF в CSV - PullRequest
0 голосов
/ 24 марта 2020

У меня есть код ниже для преобразования файла LDIF (более 100 000 строк) в файл CSV (более 4 000 строк), но я не уверен, что доволен временем, которое требуется - хотя я не знаю сколько на самом деле это займет времени; может быть, это нормальное время на моем ноутбуке (Core i5 7-го поколения, 16 ГБ ОЗУ, SSD-накопитель)?

Есть ли место для улучшения? (особенно для синтаксического анализа, если это возможно, который занимает 30 секунд)

# Reducing & editing data to process:
# -----------------------------------
$original = Get-Content $IN_ldif_file
$reduced = (($original | select-string -pattern '^cust[A-Z]','^$' -CaseSensitive).Line) -replace ':: ', ': ' -replace '^cust',''
"Writing reduced LDIF file..." # < 1 sec
(Measure-Command { Set-Content $reducedLDIF -Value $reduced -Encoding UTF8 }).TotalSeconds

# Parsing the relevant data:
# --------------------------
$inData = New-Object -TypeName System.IO.StreamReader -ArgumentList $reducedLDIF
$a = @{}                # initialize the temporary hash
$lineNum = $rcdNum = 0  # initialize the counters
"Parsing reduced LDIF file..." # 27-36 sec
(Measure-Command { 
    # Begin reading and processing the input file:
    $results = while (-not $inData.EndOfStream)
    {
        $line = $inData.ReadLine()
        Write-Verbose "$("{0:D4}" -f ++$lineNum)|$("{0:D4}|" -f $rcdNum)$line"

        if (($line -match "^\s*$") -or $inData.EndOfStream )
        {
            # blank line or end of stream - dump the hash as an object and reinit the hash
            [PSCustomObject]$a
            $a = @{}
            $rcdNum++
        } else {
            # build up hash table for the object
            $key, $value = $line -split ": "
            $a[$key] = $value
        }
    }
    $inData.Close()
}).TotalSeconds

# Populating & writing the CSV file:
# ----------------------------------
"Populating the CSV data..." # 7-11 sec
(Measure-Command { 
    $out = $results |
        select  "Attribute01",
                "Attribute02",
                "Attribute03",
                <# etc... #>
                @{n="Attribute39"; E={$_."Attribute20"}}, # Attribute39 (not in LDIF) takes value of Attribute20
                "Attribute40"
}).TotalSeconds

"Writing CSV file..." # < 1 sec
(Measure-Command { $out | Export-CSV $OUT_csv_file -NoTypeInformation }).TotalSeconds

Примечание. На самом деле мне не нужно экспортировать данные с "$ selected" в файл (например, "$ extendedLDIF"), но фрагмент кода, который я нашел для анализа, похоже, требует файла.

Спасибо!

1 Ответ

0 голосов
/ 24 марта 2020

Итак, я нашел способ сократить время разбора почти вдвое, повторно используя данные из переменной $reduced, которая уже находится в памяти:

    $a = @{}                # initialize the temporary hash
    $lineNum = $rcdNum = 0  # initialize the counters
    "Parsing reduced LDIF file..."
(Measure-Command { 
    $results = ForEach ($line in $reduced) {
        Write-Verbose "$("{0:D6}" -f ++$lineNum)|$("{0:D4}|" -f $rcdNum)$line"
        if ($line -match "^\s*$")
        {   # blank line or end of stream - dump the hash as an object and reinit the hash
            [PSCustomObject]$a
            $a = @{}
            $rcdNum++
        }
        else {
            # build up hash table for the object
            $key, $value = $line -split ": "
            $a[$key] = $value
        }
    }
}).TotalSeconds

Это уже более приемлемо (о 16 se c вместо 30).

...