Настройка производительности Powershell для операции агрегирования файлов с большими разделителями
У меня есть файл с разделителями на 350 столбцов. Разделитель
\034(Field separator)
. Мне нужно извлечь конкретное значение столбца и узнать количество каждого отдельного значения этого столбца в файле. Если количество различных значений больше или равно 2, мне нужно вывести его в файл. Размер исходного файла составляет 1 ГБ. Я написал следующую команду. Это очень медленно.
Get-Content E:\Test\test.txt | Foreach {($_ -split '\034')[117]} | Group-Object -Property { $_ } | %{ if($_.Count -ge 2) { Select-Object -InputObject $_ -Property Name,Count} } | Export-csv -Path "E:\Test\test2.csv" -NoTypeInformation
Пожалуйста помоги!
1 ответ
Я предлагаю использовать switch
оператор для быстрой обработки входного файла (по стандартам PowerShell):
# Get an array of all the column values of interest.
$allColValues = switch -File E:\Test\test.txt {
default { # each input line
# For better performance with *literal* separators,
# use the .Split() *method*.
# Generally, however, use of the *regex*-based -split *operator* is preferable.
$_.Split([char] 0x1c)[117] # hex 0x1c is octal 034
}
}
# Group the column values, and only output those that occur at least
# twice.
$allColValues | Group-Object -NoElement | Where-Object Count -ge 2 |
Select-Object Name, Count | Export-Csv E:\Test\test2.csv -NoTypeInformation
Подсказка Mathias R. Jessen за то, что он предложил
-NoElement
коммутатор, который оптимизирует вызов, сохраняя только абстрактную групповую информацию; то есть только критерии группировки (как отражено в
.Name
, а не отдельные объекты, составляющие группу (как обычно
.Group
) возвращаются через выходные объекты.
Что касается того, что вы пробовали :
с построчной потоковой передачей в конвейере происходит медленно , как обычно ( передача от объекта к объекту приводит к накладным расходам), так и, в частности , потому, что
Get-Content
украшает каждую выводимую строку метаданными ETS (Extended Type System).- В выпуске GitHub № 7537 предлагается добавить способ отказа от этого оформления.
- За счет потребления памяти и потенциально дополнительной работы по разделению строк
-Raw
switch считывает весь файл как одну многострочную строку, что намного быстрее.
Проходящий
-Property { $_ }
кGroup-Object
не обязательно - просто пропустите. Без-Property
аргумент, входные объекты группируются как единое целое .Цепочка
Where-Object
а также - вместо фильтрации черезif
заявление вForEach-Object
вызов в сочетании с несколькимиSelect-Object
звонки - не только концептуально понятнее, но и работает лучше.