我在这台服务器上没有一个像样的文本编辑器,但我需要查看某个文件中第10行错误的原因。不过我有PowerShell...
我在这台服务器上没有一个像样的文本编辑器,但我需要查看某个文件中第10行错误的原因。不过我有PowerShell...
Get-Content file.txt | Select-Object -Index (line - 1)
Get-Content file.txt | Select-Object -Index 4
(Get-Content file.txt)[4]
这将显示myfile.txt文件的第10行:
get-content myfile.txt | select -first 1 -skip 9
-first
和-skip
都是可选参数,在类似情况下,-context
或-last
也可能有用。
Get-Content
会将整个文件读入内存中。这在处理大文件时并不总是有效。 - litGet-Content
命令 的 -TotalCount
参数读取前 n
行,然后使用 Select-Object
返回第 n
行:Get-Content file.txt -TotalCount 9 | Select-Object -Last 1;
根据 @C.B. 的评论,这样做可以提高性能,只需读取到第 n
行,而不是整个文件。请注意,您可以使用别名 -First
或 -Head
替换 -TotalCount
。
# Added this for @Graimer's request ;) (not same computer, but one with HD little more
# performant...)
> measure-command { Get-Content ita\ita.txt -TotalCount 260000 | Select-Object -Last 1 }
Days : 0
Hours : 0
Minutes : 0
Seconds : 28
Milliseconds : 893
Ticks : 288932649
TotalDays : 0,000334412788194444
TotalHours : 0,00802590691666667
TotalMinutes : 0,481554415
TotalSeconds : 28,8932649
TotalMilliseconds : 28893,2649
> measure-command { (gc "c:\ps\ita\ita.txt")[260000] }
Days : 0
Hours : 0
Minutes : 0
Seconds : 9
Milliseconds : 257
Ticks : 92572893
TotalDays : 0,000107144552083333
TotalHours : 0,00257146925
TotalMinutes : 0,154288155
TotalSeconds : 9,2572893
TotalMilliseconds : 9257,2893
> measure-command { ([System.IO.File]::ReadAllLines("c:\ps\ita\ita.txt"))[260000] }
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 234
Ticks : 2348059
TotalDays : 2,71766087962963E-06
TotalHours : 6,52238611111111E-05
TotalMinutes : 0,00391343166666667
TotalSeconds : 0,2348059
TotalMilliseconds : 234,8059
> measure-command {get-content .\ita\ita.txt | select -index 260000}
Days : 0
Hours : 0
Minutes : 0
Seconds : 36
Milliseconds : 591
Ticks : 365912596
TotalDays : 0,000423509949074074
TotalHours : 0,0101642387777778
TotalMinutes : 0,609854326666667
TotalSeconds : 36,5912596
TotalMilliseconds : 36591,2596
([System.IO.File]::ReadAllLines(路径))[索引]
。ReadAllLines()
不仅更快,而且比两个Get-Content
的用法快得多。正如其名称所示,它也在读取整个文件。无论如何,如果您想尝试另一种方法,我已经发布了另一种方法。此外,每当我使用Measure-Command
来对代码进行基准测试时,我通常会像这样运行它:1..10 | % { Measure-Command { ... } } | Measure-Object TotalMilliseconds -Average -Min -Max -Sum;
这样我可以从多次测试运行中获得更准确的数字。 - Lance U. MatthewsException calling "ReadAllLines" with "1" argument(s): "Array dimensions exceeded supported range." At line:1 char:1
- Nate AndersonSystem.IO
类的函数:function GetLineAt([String] $path, [Int32] $index)
{
[System.IO.FileMode] $mode = [System.IO.FileMode]::Open;
[System.IO.FileAccess] $access = [System.IO.FileAccess]::Read;
[System.IO.FileShare] $share = [System.IO.FileShare]::Read;
[Int32] $bufferSize = 16 * 1024;
[System.IO.FileOptions] $options = [System.IO.FileOptions]::SequentialScan;
[System.Text.Encoding] $defaultEncoding = [System.Text.Encoding]::UTF8;
# FileStream(String, FileMode, FileAccess, FileShare, Int32, FileOptions) constructor
# http://msdn.microsoft.com/library/d0y914c5.aspx
[System.IO.FileStream] $input = New-Object `
-TypeName 'System.IO.FileStream' `
-ArgumentList ($path, $mode, $access, $share, $bufferSize, $options);
# StreamReader(Stream, Encoding, Boolean, Int32) constructor
# http://msdn.microsoft.com/library/ms143458.aspx
[System.IO.StreamReader] $reader = New-Object `
-TypeName 'System.IO.StreamReader' `
-ArgumentList ($input, $defaultEncoding, $true, $bufferSize);
[String] $line = $null;
[Int32] $currentIndex = 0;
try
{
while (($line = $reader.ReadLine()) -ne $null)
{
if ($currentIndex++ -eq $index)
{
return $line;
}
}
}
finally
{
# Close $reader and $input
$reader.Close();
}
# There are less than ($index + 1) lines in the file
return $null;
}
GetLineAt 'file.txt' 9;
$bufferSize
变量可能会影响性能。更简洁的版本可以使用默认缓冲区大小,并且不提供优化提示,就像这样:function GetLineAt([String] $path, [Int32] $index)
{
# StreamReader(String, Boolean) constructor
# http://msdn.microsoft.com/library/9y86s1a9.aspx
[System.IO.StreamReader] $reader = New-Object `
-TypeName 'System.IO.StreamReader' `
-ArgumentList ($path, $true);
[String] $line = $null;
[Int32] $currentIndex = 0;
try
{
while (($line = $reader.ReadLine()) -ne $null)
{
if ($currentIndex++ -eq $index)
{
return $line;
}
}
}
finally
{
$reader.Close();
}
# There are less than ($index + 1) lines in the file
return $null;
}
GetLineAt 'file.txt' 9;
$n = 60699010
$src = 'hugefile.csv'
$batch = 100
$timer = [Diagnostics.Stopwatch]::StartNew()
$count = 0
Get-Content $src -ReadCount $batch -TotalCount $n | % {
$count += $_.Length
if ($count -ge $n ) {
$_[($n - $count + $_.Length - 1)]
}
}
$timer.Stop()
$timer.Elapsed
这将打印第 $n 行和经过的时间。
Get-Content
很容易,但当涉及到真正大的文本文件时(例如 >5 GB),它就会显露出局限性。Get-Content
更快(几乎像Linux上的sed
那样快,如this):
[Linq.Enumerable] :: ElementAt([System.IO.File] :: ReadLines("<path_to_file>"), <index>)
在我的计算机上,这大约需要4秒钟才能找到~4.5 GB文件中间的一行,而(Get-Content -Path <path_to_file> -TotalCount <index>) [-1] 则需要大约35秒钟。
(get-content myfile.txt)[9]
是什么意思? - CB.