如何删除PowerShell中特定日期之前的所有记录(行)?

时间:2015-02-11 21:10:59

标签: powershell rows

我试图编写一个代码,根据第8列中存储的文本字符串删除特定日期之前的所有行(日期存储在第1列中)。我的文本文件非常大(超过80万)行)所以我不确定我的代码是否是最好的方法。到目前为止,我的代码只是在$ date1之前删除所有行。

$date1 = Read-Host 'Enter date1 mm/dd/yyyy'
$date2 = Read-Host 'Enter date2 mm/dd/yyyy'
$header="Date,Header2,Header3,Header4,Header5,Header6,Header7,Header8" | Out-File test.txt -encoding "Default"
get-content .\bigfile.txt |select -Skip 1 | where { [datetime]($_.split(','))[0] -ge $date1} | Out-File test.txt -encoding "Default" -append

因此对于第8列中的文本字符串,其中最后3个字符是" -XX"或" .YY"应删除$ date1之前的所有行。对于第8列中的文本字符串,其中最后3个字符不是" -XX"或" .YY" ,应删除$ date2之前的所有行。 我真的希望我的描述足够清楚。如果不是,我很抱歉。

请参阅下面的测试文件: bigfile.txt

Date,Header2,Header3,Header4,Header5,Header6,Header7,Header8
8/14/2014,11.4,11.4,11.07,11.11,52930,0,Text1
8/15/2014,11.18,11.18,10.78,10.81,80517,0,Text1
8/18/2014,10.92,11.12,10.81,11,188671,0,Text1
8/14/2014,11.09,11.79,11.036,11.49,142205,0,Text2-XX
8/15/2014,11.43,11.738,11.32,11.7,70846,0,Text2-XX
8/16/2014,11.67,12.56,11.458,12.42,170739,0,Text2-XX
8/17/2014,12.47,12.79,12.22,12.66,176367,0,Text2-XX
8/14/2014,12.7,13.5,12.6,13.26,411410,0,Text3
8/15/2014,13.35,13.62,13.17,13.55,209561,0,Text3
8/16/2014,13.55,13.57,13.28,13.49,104880,0,Text3
8/14/2014,13.4,13.61,13.14,13.18,167355,0,Text4.YY
8/15/2014,13.17,13.17,12.67,13.04,119659,0,Text4.YY
8/16/2014,13.07,13.07,12.64,12.73,133181,0,Text4.YY
8/15/2014,12.75,13.43,12.75,13.38,154302,0,Text5
8/16/2014,13.43,13.78,13.28,13.49,203535,0,Text5
8/17/2014,13.43,14.29,13.38,14.24,167803,0,Text5
8/18/2014,14.26,14.53,13.79,13.91,124665,0,Text5
8/19/2014,13.87,13.95,13.25,13.3,123747,0,Text5
8/20/2014,13.27,13.45,12.79,12.94,128408,0,Text5
8/21/2014,12.81,13.22,12.81,13.1,74911,0,Text5
8/15/2014,13.09,13.26,12.81,13.01,204025,0,Text5.YY
8/16/2014,13.07,13.07,12.58,12.64,75625,0,Text5.YY
8/17/2014,12.52,13.26,12.52,13.26,115968,0,Text5.YY

3 个答案:

答案 0 :(得分:1)

这是一个简单的Import-CSV,一个Where语句,使用分组,RegEx匹配,分组中的-and条件以及它们之间的-or条件。类似的东西:

Import-CSV .\bigfile.txt | 
    where { ($_.Header8 -match "(-XX|\.YY)$" -and ([datetime]$_.Date) -ge $date1) -or ($_.Header8 -notmatch "(-XX|\.YY)$" -and ([datetime]$_.Date) -ge $date2) } | 
    Export-Csv test.txt -NoTypeInformation -append

编辑:Matt指出我的日期比较逻辑是有缺陷的,因为它考虑了文件中的文字字符串。我更新了我的代码以解决这个问题。

话虽如此,请为了上帝的爱,请使用Matt的答案!我没有看到文件中有800,000行需要更新。我的答案应该可以正常工作,但它会非常缓慢,因为它会将整个文件转换为一个对象数组,解析它们,然后立即将它们全部写回来。我离开答案是因为它功能齐全,但更适合较小的文件。

编辑2:好吧,如果您没有看到Matt代码的性能提升(您可能希望在其代码中将ReadCount更改为1000或2000),请点击此处#39;我的更新代码将在将其写回文件之前删除多余的引号。

(Import-CSV C:\temp\new.txt | 
    where { ($_.Header8 -match "(-XX|\.YY)$" -and ([datetime]$_.Date) -ge $date1) -or ($_.Header8 -notmatch "(-XX|\.YY)$" -and ([datetime]$_.Date) -ge $date2) } | 
    ConvertTo-Csv -NoTypeInformation) -replace '"'| 
    set-content $output

答案 1 :(得分:1)

我希望在拥有1000行数据的情况下,这可能会表现得更好。唯一的规定是您应该手动从文件中删除第一行数据,因为此方法以块的形式读取行并且每行都有一个if语句来检查标题似乎是浪费

$output = C:\temp\test.txt

$date1 = Read-Host 'Enter date1 mm/dd/yyyy'
$date2 = Read-Host 'Enter date2 mm/dd/yyyy'

Set-Content -Path $output -Value "Date,Header2,Header3,Header4,Header5,Header6,Header7,Header8"

Get-Content C:\temp\data.log -ReadCount 500 | ForEach-Object{$_} | ForEach-Object{
    $line = $_
    $splitLine = $line -split ","
    $singleDate = [datetime]$splitLine[0]
    $queryColumn = $splitLine[7]

    If (($queryColumn -match "(-XX|\.YY)$" -and $singleDate -ge $date1) -or ($queryColumn -notmatch "(-XX|\.YY)$" -and $singleDate -ge $date2)){
        $line
    }
} | Add-Content $output

我发誓我并没有偷走Mads的逻辑。

标题帐户

我无法通过使用if语句提出一种聪明的方法来处理标头期望。 不应在处理时间上添加太多。

Get-Content C:\temp\data.log -ReadCount 500 | ForEach-Object{$_} | ForEach-Object{
    If($_ -notmatch "header"){
        $line = $_
        $splitLine = $line -split ","
        $singleDate = [datetime]$splitLine[0]
        $queryColumn = $splitLine[7]

        If (($queryColumn -match "(-XX|\.YY)$" -and $singleDate -ge $date1) -or ($queryColumn -notmatch "(-XX|\.YY)$" -and $singleDate -ge $date2)){
            $line
        }
    }
} | Add-Content $output

答案 2 :(得分:1)

我知道这已被回答,但看起来很有趣。此外,此方法可能会提供更好的性能。我使用IO.StreamReader逐行获取文件和解析,并使用IO.StreamWrite立即输出结果。我还没有验证条件..

$date1 = Read-Host 'Enter date1 mm/dd/yyyy'
$date2 = Read-Host 'Enter date2 mm/dd/yyyy'
$filePath = "path\to\bigfile.txt"
$outputfile = "outfile.txt"

$file = New-Object System.IO.StreamReader -Arg "$filePath"
$outFile = New-Object System.IO.StreamWriter -arg "$outputfile"

while ($line = $file.ReadLine()) {

$line | % {

    $items = $_.Split(',') 
    try{ 
    [datetime]$rowDate = $items[0]
    [string]$Header8 = $items[-1]            
        If($rowDate -le $date1 -and $Header8 -match "-XX|.YY")
        {$null}
        ElseIf($rowDate-le $date2 -and $Header8 -notmatch "-XX|.YY")
        {$null}
        Else {
        $outItem = $items -join ","
        $outFile.WriteLine($outItem)}
        }    
    catch [System.Exception] {$null}
        }
    }
    $file.close()
    $outFile.Close()