Quero ler um arquivo linha por linha no PowerShell. Especificamente, quero fazer um loop no arquivo, armazenar cada linha em uma variável no loop e fazer algum processamento na linha.
Eu conheço o equivalente do Bash:
while read line do
if [[ $line =~ $regex ]]; then
# work here
fi
done < file.txt
Não há muita documentação sobre loops do PowerShell.
powershell
powershell-ise
Kingamere
fonte
fonte
Get-Content
carrega o arquivo inteiro na memória de uma vez, o que irá falhar ou congelar em arquivos grandes.process
bloco e cospe outro objeto por linha no pipeline, então essa função é o problema. Quaisquer problemas com o carregamento de todo o conteúdo na memória não são culpa doGet-Content
.foreach($line in Get-Content .\file.txt)
Ele carregará o arquivo inteiro na memória antes de começar a iteração. Se você não acredita em mim, pegue um arquivo de log de 1 GB e experimente.Get-Content .\file.txt | ForEach-Object -Process {}
reconhece o pipeline e não carrega o arquivo inteiro na memória. Por padrão, Get-Content passará uma linha por vez no pipeline.Respostas:
Documentação sobre loops em PowerShell é abundante, e você pode querer verificar os seguintes tópicos da Ajuda:
about_For
,about_ForEach
,about_Do
,about_While
.Outra solução idiomática do PowerShell para o seu problema é canalizar as linhas do arquivo de texto para o
ForEach-Object
cmdlet :Em vez de correspondência de regex dentro do loop, você pode canalizar as linhas
Where-Object
para filtrar apenas aquelas em que está interessado:fonte
docs.microsoft.com
.Get-Content
tem desempenho ruim; ele tenta ler o arquivo na memória de uma vez.O leitor de arquivos C # (.NET) lê cada linha uma por uma
Melhor Performance
Ou ligeiramente menos performante
A
foreach
instrução provavelmente será um pouco mais rápida do queForEach-Object
(consulte os comentários abaixo para obter mais informações).fonte
[System.IO.File]::ReadLines("C:\path\to\file.txt") | ForEach-Object { ... }
. Aforeach
instrução carregará toda a coleção para um objeto .ForEach-Object
usa um pipeline para transmitir. Agora, aforeach
instrução provavelmente será um pouco mais rápida do que oForEach-Object
comando, mas isso porque carregar tudo na memória geralmente é mais rápido.Get-Content
ainda é terrível, no entanto.foreach()
é um pseudônimo deForeach-Object
foreach
é uma afirmação, comoif
,for
, ouwhile
.ForEach-Object
é um comando, comoGet-ChildItem
. Também há um alias padrão deforeach
paraForEach-Object
, mas ele só é usado quando há um pipeline. Veja a longa explicação emGet-Help about_Foreach
ou clique no link em meu comentário anterior, que leva a um artigo inteiro da Equipe de Scripts da Microsoft sobre as diferenças entre a instrução e o comando.Get-Alias foreach
=>Foreach-Object
, mas você está certo, há diferenças$line
para$_
no bloco de script do loop.O interruptor todo-poderoso funciona bem aqui:
Resultado:
fonte