Quiero leer un archivo línea por línea en PowerShell. Específicamente, quiero recorrer el archivo, almacenar cada línea en una variable en el bucle y hacer algún procesamiento en la línea.
Sé el equivalente de Bash:
while read line do
if [[ $line =~ $regex ]]; then
# work here
fi
done < file.txt
No hay mucha documentación sobre los bucles de PowerShell.
powershell
powershell-ise
Kingamere
fuente
fuente
Get-Content
carga todo el archivo en la memoria a la vez, lo que fallará o se congelará en archivos grandes.process
bloque y escupe otro objeto por línea en la canalización, entonces esa función es el problema. Cualquier problema con la carga del contenido completo en la memoria no es culpa deGet-Content
.foreach($line in Get-Content .\file.txt)
el archivo completo en la memoria antes de que comience a iterar. Si no me cree, obtenga un archivo de registro de 1 GB y pruébelo.Get-Content .\file.txt | ForEach-Object -Process {}
es compatible con la canalización y no cargará todo el archivo en la memoria. De forma predeterminada, Get-Content pasará una línea a la vez a través de la canalización.Respuestas:
Documentación sobre los bucles en PowerShell es mucha, y es posible que desee echa un vistazo a los siguientes temas:
about_For
,about_ForEach
,about_Do
,about_While
.Otra solución idiomática de PowerShell para su problema es canalizar las líneas del archivo de texto al
ForEach-Object
cmdlet :En lugar de hacer coincidir expresiones regulares dentro del bucle, puede canalizar las líneas
Where-Object
para filtrar solo aquellos que le interesan:fuente
docs.microsoft.com
.Get-Content
tiene mal desempeño; intenta leer el archivo en la memoria de una vez.El lector de archivos C # (.NET) lee cada línea una por una
Mejor actuación
O un poco menos eficiente
Es
foreach
probable que la declaración sea un poco más rápida queForEach-Object
(consulte los comentarios a continuación para obtener más información).fuente
[System.IO.File]::ReadLines("C:\path\to\file.txt") | ForEach-Object { ... }
. Laforeach
declaración cargará toda la colección en un objeto .ForEach-Object
utiliza una canalización para transmitir. Ahora, laforeach
declaración probablemente será un poco más rápida que elForEach-Object
comando, pero eso se debe a que cargar todo en la memoria generalmente es más rápido.Get-Content
Sin embargo, sigue siendo terrible.foreach()
es un alias deForeach-Object
foreach
es una declaración, al igual queif
,for
owhile
.ForEach-Object
es un comando, comoGet-ChildItem
. También hay un alias predeterminado deforeach
forForEach-Object
, pero solo se usa cuando hay una canalización. Vea la explicación larga enGet-Help about_Foreach
, o haga clic en el enlace en mi comentario anterior que va a un artículo completo de The Scripting Guys de Microsoft sobre las diferencias entre la declaración y el comando.Get-Alias foreach
=>Foreach-Object
, pero tienes razón, hay diferencias$line
a$_
en el bloque de script del ciclo.El interruptor todopoderoso funciona bien aquí:
Salida:
fuente