我想在導入它們之前刪除第一行約5000個文本文件。使用PowerShell刪除頂部的文本文件
我對PowerShell仍然很陌生,所以不確定要搜索什麼或如何處理這個問題。我目前的概念使用僞代碼:
set-content file (get-content unless line contains amount)
但是,我似乎無法弄清楚如何做一些像包含。
我想在導入它們之前刪除第一行約5000個文本文件。使用PowerShell刪除頂部的文本文件
我對PowerShell仍然很陌生,所以不確定要搜索什麼或如何處理這個問題。我目前的概念使用僞代碼:
set-content file (get-content unless line contains amount)
但是,我似乎無法弄清楚如何做一些像包含。
它是不是最有效的世界,但這應該工作:
get-content $file |
select -Skip 1 |
set-content "$file-temp"
move "$file-temp" $file -Force
使用變量符號,你可以不用臨時文件:
${C:\file.txt} = ${C:\file.txt} | select -skip 1
function Remove-Topline ([string[]]$path, [int]$skip=1) {
if (-not (Test-Path $path -PathType Leaf)) {
throw "invalid filename"
}
ls $path |
% { iex "`${$($_.fullname)} = `${$($_.fullname)} | select -skip $skip" }
}
skip`沒」牛逼的工作,所以我的解決辦法是
$LinesCount = $(get-content $file).Count
get-content $file |
select -Last $($LinesCount-1) |
set-content "$file-temp"
move "$file-temp" $file -Force
雖然我真的很佩服從@hoge兩個答案非常簡潔的技術和一個包裝函數來推廣它,我鼓勵upvotes它,我不得不評論其他兩個使用臨時文件的答案(它像黑板上的指甲一樣啃着我!)。
假設該文件不是很大,你可以強制管道中離散的部分操作 - 從而避免了臨時文件的必要性 - 與明智地使用括號:
(Get-Content $file | Select-Object -Skip 1) | Set-Content $file
...或以簡短的形式:
(gc $file | select -Skip 1) | sc $file
我必須做同樣的任務,gc | select ... | sc
接手4 GB的RAM我的機器上,而讀一1.6 GB的文件。在閱讀整個文件後(至少讀取字節數爲Process Explorer),至少20分鐘才完成,此時我必須殺死它。
我的解決方案是使用更多的.NET方法:StreamReader
+ StreamWriter
。 一個偉大的答案討論PERF看到這個答案:In Powershell, what's the most efficient way to split a large text file by record type?
下面是我的解決辦法。是的,它使用的是臨時文件,但對我來說,這並不重要(這是一個巨大再用SQL表的創建和插入語句文件):
PS> (measure-command{
$i = 0
$ins = New-Object System.IO.StreamReader "in/file/pa.th"
$outs = New-Object System.IO.StreamWriter "out/file/pa.th"
while(!$ins.EndOfStream) {
$line = $ins.ReadLine();
if($i -ne 0) {
$outs.WriteLine($line);
}
$i = $i+1;
}
$outs.Close();
$ins.Close();
}).TotalSeconds
,它返回:
188.1224443
$x = get-content $file
$x[1..$x.count] | set-content $file
就是這麼多。冗長的解釋如下。 Get-content返回一個數組。我們可以「索引」數組變量,如this和other腳本專家帖子所示。
例如,如果我們定義一個這樣的數組變量,
$array = @("first item","second item","third item")
所以$陣列返回
first item
second item
third item
那麼我們就可以「索引」該陣列只提取其第一元素
$array[0]
或僅其第二個
$array[1]
或range指數值從第2個到最後一個。
$array[1..$array.count]
我剛剛從網站上了解到:
Get-ChildItem *.txt | ForEach-Object { (get-Content $_) | Where-Object {(1) -notcontains $_.ReadCount } | Set-Content -path $_ }
或者您可以使用別名,使之短,像:
gci *.txt | % { (gc $_) | ? { (1) -notcontains $_.ReadCount } | sc -path $_ }
非常感謝這個解決方案。你能指出你提到的網站嗎? – giordano 2016-08-11 15:31:08
對於您可以使用此較小的文件:
& C:\ windows \ system32 \ more +1 oldfile.csv> newfile.csv | out-null
...但它不是非常有效的處理我的示例文件的16MB。它似乎沒有終止並釋放newfile.csv上的鎖定。
通過AASoft's answer啓發,我出去改善多一點:
$i
和比較與0
在每個循環try..finally
阻止總是關閉正在使用的文件$p
的開頭引用當前目錄這些變化導致了下面的代碼:
$p = (Get-Location).Path
(Measure-Command {
# Number of lines to skip
$skip = 1
$ins = New-Object System.IO.StreamReader ($p + "\test.log")
$outs = New-Object System.IO.StreamWriter ($p + "\test-1.log")
try {
# Skip the first N lines, but allow for fewer than N, as well
for($s = 1; $s -le $skip -and !$ins.EndOfStream; $s++) {
$ins.ReadLine()
}
while(!$ins.EndOfStream) {
$outs.WriteLine($ins.ReadLine())
}
}
finally {
$outs.Close()
$ins.Close()
}
}).TotalSeconds
第一個變化帶來的處理時間我60 MB文件從5.3s
降至4s
。其餘的變化更美觀。
當我嘗試運行它時,似乎它在-skip上出錯。這可能是來自不同的版本? – percent20 2010-01-15 20:41:39
-Skip是PowerShell 2.0中的Select-Object的新增功能。另外,如果這些文件都是ascii,那麼你可能想使用set-content -enc ascii。如果編碼混合在一起,那麼它會變得複雜,除非你不關心文件編碼。 – 2010-01-15 20:51:57
我安裝了PowerShell 2.0,它現在正在工作。 – percent20 2010-01-15 21:06:14