Могу ли я пропустить строку заголовка файла CSV, используя Where-Object? - PullRequest
0 голосов
/ 16 мая 2018

Я хотел бы использовать следующий скрипт, чтобы привести огромный CSV-файл к полезному состоянию, но он устраняет строку заголовка CSV. Из прочитанных здесь вопросов / решений я понимаю, что я могу использовать Select -Skip 1 или Select -Skip 1 для сохранения заголовка, но я не уверен, как изящно интегрировать Select в мой скрипт. Нужно ли начинать все сначала или у кого-то есть простое решение?

$SourceFile = 'C:\Temp\Monthly_Report.CSV'
$Pattern = '.GBL|.aspx'

(Get-Content $SourceFile) | Where-Object {
    $_ -match $Pattern
} | Set-Content $SourceFile

Это содержимое файла "Monthly_Report.CSV" перед запуском сценария:

Monthy_Report.CSV

Ответы [ 3 ]

0 голосов
/ 17 мая 2018

Есть несколько решений вашей проблемы.

  • Используйте Import-Csv и Export-Csv, которые преобразуют входной CSV в список объектов и обратно.

    (Import-Csv $SourceFile) | Where-Object {
        $_.SomeProperty -match $Pattern
    } | Export-Csv $SourceFile -NoType
    

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

  • Поскольку вы все равно читаете весь файл в память (из-за того, что Get-Content находится в скобках), вы также можете хранить содержимое в переменной и выборочно записывать его обратно:

    $data = Get-Content $SourceFile
    
    $data | Select-Object -First 1 | Set-Content $SourceFile
    $data | Where-Object {
        $_ -match $Pattern
    } | Add-Content $SourceFile
    
  • Сценарий Where-Object может содержать не только условия, но и другие операторы, такие как операции присваивания, поэтому вы можете использовать индикатор «первой строки», например:

    $script:firstline = $true
    (Get-Content $SourceFile) | Where-Object {
        $script:firstline -or $_ -match $Pattern
        $script:firstline = $false
    } | Set-Content $SourceFile
    
  • Вы можете включить совпадение заголовка в свое регулярное выражение:

    $Pattern = '^UserID|.GBL|.aspx'
    
    (Get-Content $SourceFile) | Where-Object {
        $_ -match $Pattern
    } | Set-Content $SourceFile
    

    Мне это кажется довольно хакерским, поэтому я бы не советовал делать это на самом деле.

0 голосов
/ 17 мая 2018

Вот простое решение, которое использует множественное назначение для отделения заголовка от тела и опирается на тот факт, что -match работает с коллекциями:

$SourceFile = 'C:\Temp\Monthly_Report.CSV'
$Pattern = '\.GBL|\.aspx'

$header, $body = Get-Content $SourceFile
$body =  @($body) -match $Pattern
$header, $body | Set-Content $SourceFile
0 голосов
/ 16 мая 2018

Вам не нужно использовать параметр -skip, чтобы вообще сохранить заголовок.Я думаю, что вы неправильно понимаете это.Причина, по которой ваши заголовки отсутствуют в содержимом, заключается в том, что он не соответствует вашей переменной $ Pattern и отфильтровывается.

Вам нужно сделать что-то вроде этого:

$header = (Get-Content $SourceFile) | Select-Object -First 1
Write-Output $header 

$content = (Get-Content $SourceFile) | Where-Object { $_ -match $Pattern } 
$header + "`n" + $content | Set-Content $SourceFile
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...