[英]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"
以下是其作用的細分:
首先是那些現在熟悉的別名。 我只是把它們放進去是因為命令足夠長,所以這有助於保持事情的可管理性:
gc
表示Get-Content
%
表示Foreach
$_
用於當前管道值(這不是別名,但我想我會定義它,因為你說你是新的)好的,現在這里發生了什么:
(gc "c:\\myfile.txt") |
--> 獲取c:\\myfile.txt
的內容並將其向下發送%
--> 執行 foreach 循環(單獨遍歷管道中的每個項目)-Begin {$test = (gc "c:\\myfile.txt" | select -first 1 -last 1)}
--> 這是一個開始塊,它在進入管道之前運行這里的所有內容。 它將c:\\myfile.txt
的第一行和最后一行加載到一個數組中,以便我們可以檢查第一項和最后一項-Process {if ( $_ -eq $test[0] -or $_ -eq $test[-1] )
--> 這會檢查管道中的每個項目,檢查它是第一個還是最后一個項目在文件中{ $_ -replace "-" } else { $_ }
--> 如果是第一個或最后一個,則進行替換,如果不是,則不理會它| 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.