在 PowerShell 中逐行读取文件

Read file line by line in PowerShell

我想在 PowerShell 中逐行读取文件。具体来说,我想循环遍历文件,在循环中将每一行存储在一个变量中,并对该行做一些处理。

我知道 Bash 等效项:

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

关于 PowerShell 循环的文档不多。

Not much documentation on PowerShell loops.

有关 PowerShell 循环的文档很多,您可能需要查看以下帮助主题:about_For, about_ForEach, about_Do, about_While

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

解决您的问题的另一个惯用的 PowerShell 解决方案是将文本文件的行通过管道传输到 ForEach-Object cmdlet:

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

您可以通过 Where-Object 来过滤您感兴趣的内容,而不是在循环内进行正则表达式匹配:

Get-Content .\file.txt | Where-Object {$_ -match $regex} | ForEach-Object {
    # Work here
}

Get-Content表现不佳;它尝试一次将文件读入内存。

C# (.NET) 文件reader逐行读取

最佳表现

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

或性能稍差

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

foreach 语句可能会比 ForEach-Object 稍快(有关更多信息,请参阅下面的评论)。

万能的switch在这里很好用:

'one
two
three' > file

$regex = '^t'

switch -regex -file file { 
  $regex { "line is $_" } 
}

输出:

line is two
line is three

逐行读取大文件

原始评论 (1/2021) 通过以下命令,我能够在大约 50 秒内读取一个 4GB 的日志文件。您可以使用 PowerShell 将其作为 C# 程序集动态加载,从而加快速度。

[System.IO.StreamReader]$sr = [System.IO.File]::Open($file, [System.IO.FileMode]::Open)
while (-not $sr.EndOfStream){
    $line = $sr.ReadLine()
}
$sr.Close() 

附录 (3/2022) 使用 PowerShell 中嵌入的 C# 处理大文件速度更快,“陷阱”更少。

$code = @"
using System;
using System.IO;

namespace ProcessLargeFile
{
    public class Program
    {
        static void ProcessLine(string line)
        {
            return;
        }

        public static void ProcessLogFile(string path) {
            var start_time = DateTime.Now;
            StreamReader sr = new StreamReader(File.Open(path, FileMode.Open));
            try {
                while (!sr.EndOfStream){
                    string line = sr.ReadLine();
                    ProcessLine(line);
                }
            } finally {
                sr.Close();
            }
            var end_time = DateTime.Now;
            var run_time = end_time - start_time;
            string msg = "Completed in " + run_time.Minutes + ":" + run_time.Seconds + "." + run_time.Milliseconds;
            Console.WriteLine(msg);
        }

        static void Main(string[] args)
        {
            ProcessLogFile("c:\users\tasaif\fake.log");
            Console.ReadLine();
        }
    }
}
"@
 
Add-Type -TypeDefinition $code -Language CSharp

PS C:\Users\tasaif> [ProcessLargeFile.Program]::ProcessLogFile("c:\users\tasaif\fake.log")
Completed in 0:17.109