programing

PowerShell로 파일의 특정 줄을 인쇄하는 방법은 무엇입니까?

javamemo 2023. 8. 13. 09:02
반응형

PowerShell로 파일의 특정 줄을 인쇄하는 방법은 무엇입니까?

이 서버에는 제대로 된 텍스트 편집기가 없지만 특정 파일의 10행에 오류가 발생하는 원인을 확인해야 합니다.PowerShell은 있지만...

select:를 사용하는 것만큼 쉽습니다.

Get-Content file.txt | Select -Index (line - 1)

예: 5호선 받기

Get-Content file.txt | Select -Index 4

또는 다음을 사용할 수 있습니다.

(Get-Content file.txt)[4]

이것은 제 파일의 10번째 줄을 보여줄 것입니다.txt:

get-content myfile.txt | select -first 1 -skip 9

둘다요.-first그리고.-skip는 선택적 매개 변수입니다.-context또는-last유사한 상황에서 유용할 수 있습니다.

사용할 수 있습니다.-TotalCount첫 번째를 읽을 cmdlet 매개 변수n선, 다음 사용Select-Object반품만 가능합니다.n줄:

Get-Content file.txt -TotalCount 9 | Select-Object -Last 1;

코멘트에 따라 from @C.B. th is는 다음을 포함하여 읽기만 하여 성능을 향상시켜야 합니다.n전체 파일이 아닌 줄입니다.별칭을 사용할 수 있습니다.-First또는-Head대신에-TotalCount.

를 사용하는 기능이 있습니다.NET의 클래스 직접:

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;

재미로, 여기 몇 가지 테스트가 있습니다.

# 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( path ))[index]

메모리 소비를 줄이고 검색 속도를 높이려면 Get-Content cmdlet(https://technet.microsoft.com/ru-ru/library/hh849787.aspx) 의 -ReadCount 옵션을 사용할 수 있습니다.

이렇게 하면 대용량 파일로 작업할 때 시간이 절약될 수 있습니다.

다음은 예입니다.

$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사용하기 쉽지만 실제로 큰 텍스트 파일(예: 5GB 이상)에 대해서는 한계가 있습니다.

나는 전체 파일을 메인 메모리에 로드할 필요가 없고 그것보다 훨씬 빠른 해결책을 찾았습니다.Get-Content(만큼 빠른 속도로 실행sedLinux에서 다음과 같이):

[Linq.Enumerable]::ElementAt([System.IO.File]::ReadLines("<path_to_file>"), <index>)

컴퓨터에서 최대 4.5GB 파일의 중간에 있는 줄을 찾는 데 약 4초가 걸립니다. 반면,(Get-Content -Path <path_to_file> -TotalCount <index>)[-1]약 35초 정도 걸립니다.

언급URL : https://stackoverflow.com/questions/14759649/how-to-print-a-certain-line-of-a-file-with-powershell

반응형