Читать файл построчно в PowerShell

Я хочу прочитать файл построчно в PowerShell. В частности, я хочу пройтись по файлу, сохранить каждую строку в переменной в цикле и выполнить некоторую обработку в строке.

Я знаю эквивалент Bash:

while read line do
    if [[ $line =~ $regex ]]; then
          # work here
    fi
done < file.txt

Не много документации по циклам PowerShell.

6 ответов

Решение

Не много документации по циклам PowerShell.

Документация по циклам в PowerShell обильна, и вы можете проверить следующие разделы справки: about_For, about_ForEach, about_Do, about_While,

foreach($line in Get-Content .\file.txt) {
    if($line -match $regex){
        # Work here
    }
}

Другое идиоматическое решение PowerShell для вашей проблемы - это передача строк текстового файла в ForEach-Object командлет:

Get-Content .\file.txt | ForEach-Object {
    if($_ -match $regex){
        # Work here
    }
}

Вместо сопоставления регулярных выражений в цикле, вы можете передать линии через Where-Object отфильтровать только те, которые вас интересуют:

Get-Content .\file.txt | Where-Object {$_ -match $regex} | ForEach-Object {
    # Work here
}

Get-Content имеет плохую производительность; он пытается прочитать файл в память все сразу.

C# (.NET) программа для чтения файлов читает каждую строку одну за другой

Лучший спектакль

foreach($line in [System.IO.File]::ReadLines("C:\path\to\file.txt"))
{
       $line
}

Или же

[System.IO.File]::ReadLines("C:\path\to\file.txt") | ForEach-Object {
       $_
}

foreach утверждение, вероятно, будет немного быстрее, чем ForEach-Object, но это потому, что загрузка всего этого в память обычно происходит быстрее.

Я смог прочитать файл журнала размером 4 ГБ примерно за 50 секунд со следующим. Вы можете сделать это быстрее, загрузив его как сборку C# динамически с помощью PowerShell.

      [System.IO.StreamReader]$sr = [System.IO.File]::Open($file, [System.IO.FileMode]::Open)
while (-not $sr.EndOfStream){
    $line = $sr.ReadLine()
}
$sr.Close() 

Здесь хорошо работает всемогущий переключатель:

'one
two
three' > file

$regex = '^t'

switch -regex -file file { 
  $regex { "line is $_" } 
}

Выход:

line is two
line is three
      
Set-Location 'C:\files'
$files = Get-ChildItem -Name -Include *.txt
foreach($file in $files){
        Write-Host("Start Reading file: " + $file)
        foreach($line in Get-Content $file){
            Write-Host($line)
        }
        Write-Host("End Reading file: " + $file)                
}

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

Вы можете зациклить массив для чтения каждой строки.

$ TxtContent = Get-content -Path "C: \ path \ TestFile.txt"

$ TxtContent 1
$ TxtContent [2]

[См. Это для полного примера]: http://dotnet-helpers.com/powershell-demo/reading-from-text-files-with-powershell/

Другие вопросы по тегам