添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

I want to read a file line by line in PowerShell. Specifically, I want to loop through the file, store each line in a variable in the loop, and do some processing on the line.

I know the Bash equivalent:

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

Not much documentation on PowerShell loops.

The selected answer from Mathias is not a great solution. Get-Content loads the entire file into memory at once, which will fail or freeze on large files. – Kolob Canyon Jun 7 at 18:23 @KolobCanyon that is completely untrue. By default Get-Content loads each line as one object in the pipeline. If you're piping to a function that doesn't specify a process block, and spits out another object per line into the pipeline, then that function is the problem. Any problems with loading the full content into memory are not the fault of Get-Content. – The Fish Jul 4 at 12:39 @TheFish foreach($line in Get-Content .\file.txt) It will load the entire file into memory before it begins iterating. If you don't believe me, go get a 1GB log file and try it. – Kolob Canyon Jul 5 at 15:00 @KolobCanyon That's not what you said. You said that Get-Content loads it all into memory which is not true. Your changed example of foreach would, yes; foreach is not pipeline aware. Get-Content .\file.txt | ForEach-Object -Process {} is pipeline aware, and will not load the entire file into memory. By default Get-Content will pass one line at a time through the pipeline. – The Fish Jul 8 at 10:46

Documentation on loops in PowerShell is plentiful, and you might want to check out the following help topics: about_For, about_ForEach, about_Do, about_While.

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

Another idiomatic PowerShell solution to your problem is to pipe the lines of the text file to the ForEach-Object cmdlet:

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

Instead of regex matching inside the loop, you could pipe the lines through Where-Object to filter just those you're interested in:

Get-Content .\file.txt | Where-Object {$_ -match $regex} | ForEach-Object {
    # Work here
                The links are not broken, but they now redirect to docs.microsoft.com.
                    – Peter Mortensen
                Sep 19 '17 at 20:05

Get-Content has bad performance; it tries to read the file into memory all at once.

C# (.NET) file reader reads each line one by one

Best Performace

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

Or slightly less performant

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

The foreach statement will likely be slightly faster than ForEach-Object (see comments below for more information).

I would probably use [System.IO.File]::ReadLines("C:\path\to\file.txt") | ForEach-Object { ... }. The foreach statement will load the entire collection to an object. ForEach-Object uses a pipeline to stream with. Now the foreach statement will likely be slightly faster than the ForEach-Object command, but that's because loading the whole thing to memory usually is faster. Get-Content is still terrible, however. – Bacon Bits Nov 7 '17 at 0:11 That is a very common misconception. foreach is a statement, like if, for, or while. ForEach-Object is a command, like Get-ChildItem. There is also a default alias of foreach for ForEach-Object, but it is only used when there is a pipeline. See the long explanation in Get-Help about_Foreach, or click the link in my previous comment which goes to an entire article by Microsoft's The Scripting Guys about the differences between the statement and the command. – Bacon Bits Nov 7 '17 at 13:10 @BaconBits blogs.technet.microsoft.com/heyscriptingguy/2014/07/08/… Learned something new. Thanks. I assumed they were the same because Get-Alias foreach => Foreach-Object, but you are right, there are differences – Kolob Canyon Nov 7 '17 at 15:07 That will work, but you'll want to change $line to $_ in the loop's script block. – Bacon Bits May 15 '18 at 18:10

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.

site design / logo © 2019 Stack Exchange Inc; user contributions licensed under cc by-sa 4.0 with attribution required. rev 2019.9.26.35031