簡體   English   中英

如何搜索文本文件中的第一行和最后一行?

[英]How can I search the first line and the last line in a text file?

我只需要搜索文本文件中的第一行和最后一行即可找到“-”並將其刪除。 我該怎么做? 我試過選擇字符串,但我不知道找到第一行和最后一行,只從那里刪除“-”。

這是文本文件的樣子:

 % 01-A247M15 G70 
N0001 G30 G17 X-100 Y-100 Z0
N0002 G31 G90 X100 Y100 Z45
N0003 ; --PART NO.:  NC-HON.PHX01.COVER-SHOE.DET-1000.050 
N0004 ; --TOOL:  8.55 X .3937 
N0005 ;  
N0006  % 01-A247M15 G70 

像這樣的東西?

$1 = Get-Content C:\work\test\01.I

$1 | select-object -index 0, ($1.count-1)

嘗試:

$txt = get-content c:\myfile.txt
$txt[0] = $txt[0] -replace '-'
$txt[$txt.length - 1 ] = $txt[$txt.length - 1 ] -replace '-'
$txt | set-content c:\myfile.txt

好的,所以在看了一會兒之后,我決定必須有一種方法可以用一個襯里來做到這一點。 這里是:

(gc "c:\myfile.txt") | % -Begin {$test = (gc "c:\myfile.txt" | select -first 1 -last 1)} -Process {if ( $_ -eq $test[0] -or $_ -eq $test[-1] ) { $_ -replace "-" } else { $_ }} | Set-Content "c:\myfile.txt"

以下是其作用的細分:

首先是那些現在熟悉的別名。 我只是把它們放進去是因為命令足夠長,所以這有助於保持事情的可管理性:

  1. gc表示Get-Content
  2. %表示Foreach
  3. $_用於當前管道值(這不是別名,但我想我會定義它,因為你說你是新的)

好的,現在這里發生了什么:

  1. (gc "c:\\myfile.txt") | --> 獲取c:\\myfile.txt的內容並將其向下發送
  2. % --> 執行 foreach 循環(單獨遍歷管道中的每個項目)
  3. -Begin {$test = (gc "c:\\myfile.txt" | select -first 1 -last 1)} --> 這是一個開始塊,它在進入管道之前運行這里的所有內容。 它將c:\\myfile.txt的第一行和最后一行加載到一個數組中,以便我們可以檢查第一項和最后一項
  4. -Process {if ( $_ -eq $test[0] -or $_ -eq $test[-1] ) --> 這會檢查管道中的每個項目,檢查它是第一個還是最后一個項目在文件中
  5. { $_ -replace "-" } else { $_ } --> 如果是第一個或最后一個,則進行替換,如果不是,則不理會它
  6. | Set-Content "c:\\myfile.txt" | Set-Content "c:\\myfile.txt" --> 這會將新值放回文件中。

請訪問以下網站以獲取有關這些項目的更多信息:

Get-Content 用途
獲取內容定義
Foreach
管道
Foreach 的開始和處理部分(這通常用於自定義函數,但它們也適用於 foreach 循環)
If ... else語句
設置內容

所以我在考慮如果你想對許多文件這樣做,或者想經常這樣做。 我決定制作一個可以滿足您要求的功能。 這是函數:

function Replace-FirstLast {
    [CmdletBinding()]
    param(
        [Parameter( `
            Position=0, `
            Mandatory=$true)]
        [String]$File,
        [Parameter( `
            Position=1, `
            Mandatory=$true)]
        [ValidateNotNull()]
        [regex]$Regex,
        [Parameter( `
            position=2, `
            Mandatory=$false)]
        [string]$ReplaceWith=""
    )

Begin {
    $lines = Get-Content $File
} #end begin 

Process {
    foreach ($line in $lines) {
        if ( $line -eq $lines[0]  ) {
            $lines[0] = $line -replace $Regex,$ReplaceWith 
        } #end if
        if ( $line -eq $lines[-1] ) {
            $lines[-1] = $line -replace $Regex,$ReplaceWith
        }
    } #end foreach
}#End process

end {
    $lines | Set-Content $File
}#end end

} #end function

這將創建一個名為Replace-FirstLast的命令。 它會被這樣調用:

Replace-FirstLast -File "C:\myfiles.txt" -Regex "-" -ReplaceWith "NewText"

-Replacewith是可選的,如果它是空白的,它只會刪除(默認值"" )。 -Regex正在尋找一個正則表達式來匹配您的命令。 有關將其放入您的個人資料的信息,請查看這篇文章

請注意:如果您的文件非常大(幾 GB),這不是最佳解決方案。 這將導致整個文件存在於內存中,這可能會導致其他問題。

您可以使用select-object cmdlet 來幫助您完成此操作,因為get-content基本上將文本文件作為一個巨大的數組吐出。

因此,你可以做這樣的事情

get-content "path_to_my_awesome_file" | select -first 1 -last 1

要在此之后刪除破折號,您可以使用-Replace開關來查找破折號並將其刪除。 這比使用System.String.Replace(...)方法更好,因為它可以匹配正則表達式語句並替換整個字符串數組!

那看起來像:

# gc = Get-Content. The parens tell Powershell to do whatever's inside of it 
# then treat it like a variable.
(gc "path_to_my_awesome_file" | select -first 1 -last 1) -Replace '-',''

如果您的文件非常大,您可能不想讀取整個文件來獲取最后一行。 gc -Tail 會很快為您找到最后一行。

function GetFirstAndLastLine($path){

    return  New-Object PSObject -Property @{        
        First = Get-Content $path -TotalCount 1
        Last = Get-Content $path -Tail 1
        }
}

GetFirstAndLastLine "u_ex150417.log"

我在一個 20 GB 的日志文件上嘗試了這個,它立即返回。 讀取文件需要幾個小時。

如果您想保留所有刪除的內容並且只想從末尾刪除,您仍然需要閱讀該文件。 使用 -Tail 是檢查它是否存在的快速方法。

我希望它有幫助。

對上述問題的更清晰的回答:

$Line_number_were_on = 0
$Awesome_file = Get-Content "path_to_ridiculously_excellent_file" | %{ 
    $Line = $_ 
    if ($Line_number_were_on -eq $Awesome_file.Length) 
         { $Line -Replace '-','' } 
    else 
         { $Line } ; 
    $Line_number_were_on++ 
} 

我喜歡單行,但我發現當我把簡潔放在函數上時,可讀性有時會受到影響。 如果您正在做的將成為其他人將閱讀/維護的腳本的一部分,那么可讀性可能是需要考慮的。

按照尼克的回答:我確實需要對目錄樹中的所有文本文件執行此操作,這就是我現在正在使用的:

Get-ChildItem -Path "c:\work\test" -Filter *.i | where { !$_.PSIsContainer } | % { 
$txt = Get-Content $_.FullName; 
$txt[0] = $txt[0] -replace '-'; 
$txt[$txt.length - 1 ] = $txt[$txt.length - 1 ] -replace '-';
$txt | Set-Content $_.FullName
}

看起來它現在運行良好。

簡單的過程:用你的文件名替換 $file.txt

獲取內容 $file_txt | 選擇對象 -last 1

我最近在 .bat 文件的最后一行中搜索注釋。 好像把之前命令的錯誤代碼搞亂了。 我發現這對於在最后一行文件中搜索模式很有用。 Pspath 是獲取內容輸出的隱藏屬性。 如果我使用 select-string,我會丟失文件名。 *.bat 被作為 -filter 傳遞以提高速度。

get-childitem -recurse . *.bat | get-content -tail 1 | where { $_ -match 'rem' } | 
  select pspath


PSPath
------
Microsoft.PowerShell.Core\FileSystem::C:\users\js\foo\file.bat

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM