Je souhaite lire un fichier ligne par ligne dans PowerShell. Plus précisément, je souhaite parcourir le fichier, stocker chaque ligne dans une variable de la boucle et effectuer un traitement sur la ligne.
Je connais l'équivalent Bash:
while read line do
if [[ $line =~ $regex ]]; then
# work here
fi
done < file.txt
Pas beaucoup de documentation sur les boucles PowerShell.
powershell
powershell-ise
Kingamere
la source
la source
Get-Content
charge le fichier entier en mémoire à la fois, ce qui échouera ou se bloquera sur les gros fichiers.process
bloc et crache un autre objet par ligne dans le pipeline, alors cette fonction est le problème. Les problèmes de chargement du contenu complet en mémoire ne sont pas la faute deGet-Content
.foreach($line in Get-Content .\file.txt)
Il chargera le fichier entier en mémoire avant de commencer l'itération. Si vous ne me croyez pas, allez chercher un fichier journal de 1 Go et essayez-le.Get-Content .\file.txt | ForEach-Object -Process {}
est compatible avec le pipeline et ne chargera pas le fichier entier en mémoire. Par défaut, Get-Content passera une ligne à la fois dans le pipeline.Réponses:
Documentation sur les boucles dans PowerShell est abondante, et vous pouvez consulter les rubriques d'aide suivantes:
about_For
,about_ForEach
,about_Do
,about_While
.Une autre solution PowerShell idiomatique à votre problème consiste à diriger les lignes du fichier texte vers l'
ForEach-Object
applet de commande :Au lieu de faire correspondre les expressions régulières à l'intérieur de la boucle, vous pouvez faire passer les lignes
Where-Object
pour filtrer uniquement ceux qui vous intéressent:la source
docs.microsoft.com
.Get-Content
a de mauvaises performances; il essaie de lire le fichier en mémoire en une seule fois.Le lecteur de fichiers C # (.NET) lit chaque ligne une par une
Meilleure performance
Ou un peu moins performant
La
foreach
déclaration sera probablement légèrement plus rapide queForEach-Object
(voir les commentaires ci-dessous pour plus d'informations).la source
[System.IO.File]::ReadLines("C:\path\to\file.txt") | ForEach-Object { ... }
. L'foreach
instruction chargera la collection entière dans un objet .ForEach-Object
utilise un pipeline pour diffuser. Maintenant, l'foreach
instruction sera probablement légèrement plus rapide que laForEach-Object
commande, mais c'est parce que le chargement de l'ensemble en mémoire est généralement plus rapide.Get-Content
est toujours terrible, cependant.foreach()
est un alias deForeach-Object
foreach
est une déclaration, commeif
,for
ouwhile
.ForEach-Object
est une commande, commeGet-ChildItem
. Il existe également un alias par défaut deforeach
forForEach-Object
, mais il n'est utilisé que lorsqu'il existe un pipeline. Voir la longue explication dansGet-Help about_Foreach
, ou cliquez sur le lien dans mon commentaire précédent qui mène à un article entier de The Scripting Guys de Microsoft sur les différences entre la déclaration et la commande.Get-Alias foreach
=>Foreach-Object
, mais vous avez raison, il y a des différences$line
pour$_
dans le bloc de script de la boucle.L'interrupteur tout-puissant fonctionne bien ici:
Production:
la source