Lees bestand regel voor regel in PowerShell

Ik wil een bestand regel voor regel lezen in PowerShell. Ik wil met name door het bestand lopen, elke regel in een variabele in de lus opslaan en wat bewerkingen op de regel uitvoeren.

Ik ken het Bash-equivalent:

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

Niet veel documentatie over PowerShell-lussen.


Antwoord 1, autoriteit 100%

Niet veel documentatie over PowerShell-lussen.

Documentatie over lussen in PowerShell is overvloedig, en misschien wilt u de volgende Help-onderwerpen bekijken: about_For, about_ForEach, about_Do, about_While.

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

Een andere idiomatische PowerShell-oplossing voor uw probleem is om de regels van het tekstbestand te pipen naar de ForEach-Objectcmdlet:

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

In plaats van regex-overeenkomsten in de lus, kunt u de regels door Where-Objectom alleen die te filteren waarin u geïnteresseerd bent:

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

Antwoord 2, autoriteit 28%

Get-Contentpresteert slecht; het probeert het bestand in één keer in het geheugen te lezen.

C# (.NET)-bestandslezer leest elke regel één voor één

Beste prestatie

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

Of iets minder presterend

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

De foreach-instructie zal waarschijnlijk iets sneller zijn dan ForEach-Object(zie opmerkingen hieronder voor meer informatie).


Antwoord 3, autoriteit 2%

De almachtige switchwerkt hier goed:

'one
two
three' > file
$regex = '^t'
switch -regex -file file { 
  $regex { "line is $_" } 
}

Uitvoer:

line is two
line is three

Antwoord 4

Ik kon een logbestand van 4 GB in ongeveer 50 seconden lezen met het volgende. Je kunt het misschien sneller maken door het dynamisch te laden als een C#-assembly met PowerShell.

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

Other episodes