在 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
我想在 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