Chcę czytać plik wiersz po wierszu w programie PowerShell. W szczególności chcę przejrzeć plik w pętli, zapisać każdy wiersz w zmiennej w pętli i wykonać pewne przetwarzanie w wierszu.
Znam odpowiednik Bash:
while read line do
if [[ $line =~ $regex ]]; then
# work here
fi
done < file.txt
Niewiele dokumentacji na temat pętli programu PowerShell.
powershell
powershell-ise
Kingamere
źródło
źródło
Get-Content
ładuje cały plik do pamięci naraz, co powoduje błąd lub zawieszanie się w przypadku dużych plików.process
bloku, i wypluwa inny obiekt w każdym wierszu do potoku, to ta funkcja jest problemem. Ewentualne problemy z wczytaniem pełnej zawartości do pamięci nie są spowodowaneGet-Content
.foreach($line in Get-Content .\file.txt)
cały plik do pamięci przed rozpoczęciem iteracji. Jeśli mi nie wierzysz, weź plik dziennika 1 GB i wypróbuj.Get-Content .\file.txt | ForEach-Object -Process {}
jest świadomy potoku i nie załaduje całego pliku do pamięci. Domyślnie Get-Content będzie przekazywać po jednym wierszu przez potok.Odpowiedzi:
Dokumentacja na pętli w PowerShell jest obfite, a może chcesz sprawdzić następujące tematy pomocy:
about_For
,about_ForEach
,about_Do
,about_While
.Innym idiomatycznym rozwiązaniem problemu w programie PowerShell jest przesyłanie wierszy z pliku tekstowego do polecenia
ForEach-Object
cmdlet :Zamiast dopasowywania wyrażeń regularnych wewnątrz pętli, możesz przepuścić linie,
Where-Object
aby przefiltrować tylko te, które Cię interesują:źródło
docs.microsoft.com
.Get-Content
ma złą wydajność; próbuje od razu wczytać plik do pamięci.Czytnik plików C # (.NET) czyta każdy wiersz po kolei
Najlepsza wydajność
Lub nieco mniej wydajne
foreach
Oświadczenie będzie prawdopodobnie nieco szybciej niżForEach-Object
(patrz komentarze poniżej, aby uzyskać więcej informacji).źródło
[System.IO.File]::ReadLines("C:\path\to\file.txt") | ForEach-Object { ... }
.foreach
Oświadczenie będzie załadować całą kolekcję do obiektu .ForEach-Object
używa potoku do przesyłania strumieniowego. Terazforeach
instrukcja prawdopodobnie będzie nieco szybsza niżForEach-Object
polecenie, ale to dlatego, że ładowanie całości do pamięci zwykle jest szybsze.Get-Content
jest jednak nadal straszna.foreach()
jest aliasemForeach-Object
foreach
jest stwierdzenie, jakif
,for
lubwhile
.ForEach-Object
to polecenie, jakGet-ChildItem
. Istnieje również domyślny aliasforeach
forForEach-Object
, ale jest on używany tylko wtedy, gdy istnieje potok. Zobacz długie wyjaśnienie wGet-Help about_Foreach
lub kliknij łącze w moim poprzednim komentarzu, który prowadzi do całego artykułu The Scripting Guys firmy Microsoft na temat różnic między instrukcją a poleceniem.Get-Alias foreach
=>Foreach-Object
, ale masz rację, są różnice$line
na$_
w bloku skryptu pętli.Wszechmocny przełącznik działa tutaj dobrze:
Wynik:
źródło