2013-01-18 96 views
5

我只需要在文本文件中搜索第一行和最後一行來查找「 - 」並將其刪除。 我該怎麼辦? 我試過選擇字符串,但我不知道找到第一行和最後一行,只從那裏刪除「 - 」。如何搜索文本文件的第一行和最後一行?

這裏是文本文件看起來像:

% 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) 

回答

5

好了,所以在這找了一段時間後,我決定必須有一種方法用一個襯墊做到這一點。那就是:

(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. $_是當前管道值(這ISN 「T的別名,但我想我會定義它,因爲你說你是新的)

好了,現在這裏是在此發生的事情:

  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" - >這使新值迴文件。

請參看下面的網站的詳細信息,其中的每一項:在Foreach的

Get-Content uses
Get-Content definition
Foreach
The Pipeline
Begin and Process部分(這通常是自定義的功能,但他們也在foreach循環中工作)
If ... else陳述
Set-Content

所以我在想,如果你想要做什麼這許多文件,或想經常這樣做。我決定做一個能夠完成你所問的功能。這裏是功能:

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正在尋找一個正則表達式來匹配你的命令。有關將其放至您的個人資料檢查信息this article

請注意:如果文件非常大(幾個GB),這是不是最好的解決辦法。這會導致整個文件存儲在內存中,這可能會導致其他問題。

+0

很好的答案,但請注意,如果文件變大,則在begin語句中使用'get-content -First 1'和'-Last 1'會更好,因此您不必將xxGB文件保留在處理時的內存。 –

+0

確實如此,但是我們又回到了沒有把整個文件傳回去的問題,只是第一行和最後一行。 – Nick

+0

沒有。我在開頭聲明「foreach -begin {..here ...}'中說過。 :) –

6

嘗試:

$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 
+2

錯別字:$ a - > $ txt(最後一行)。 $ txt [1] - > $ txt [0] :-) –

+0

Hoo ..謝謝!現在修好! –

+1

nope ..仍然是最後一行(wtf是$ a?)hehe:P –

1

可以使用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 '-','' 
+0

我也這麼想,我發現的唯一問題是他需要整個陣列。如果您試圖將其回送到文件中,它將只包含第一行和最後一行,而不是整個文件的第一行和最後一行發生更改。 – Nick

+1

另外,它應該是'gc'作爲'Get-Content'的別名。 'gci'是'Get-ChildItem'的別名 – Nick

+0

感謝您糾正我;我經常使用'cat',有時我忘記了cmdlet的全名。 :) –

0

一個清潔的回答以上:

$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++ 
} 

我喜歡的俏皮話,但我發現,可讀性往往當我把簡潔了功能有時會受到影響。如果你正在做的事情將成爲其他人將閱讀/維護的腳本的一部分,可讀性可能需要考慮。

+0

這個腳本有幾個問題。首先,它只能在最後一行工作,而不是首先和最後一行。其次,'$ line'永遠不會放回任何東西,所以工作完成後丟失,永遠放回到文件中。 – Nick

0

繼尼克的回答是:我需要做這在目錄樹中的所有文本文件,這是我現在使用什麼:

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 
} 

,它看起來像它現在運作良好。

0

如果您的文件非常大,您可能不想讀取整個文件以獲取最後一行。 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是檢查它是否存在的快速方法。

我希望它能幫助。

0

工藝簡單: 替換$ file.txt的與你的文件名

獲取內容$ file_txt | Select-Object -last 1

相關問題