Csv 何处是具有复杂求值的对象

Csv 何处是具有复杂求值的对象,csv,powershell,pipe,Csv,Powershell,Pipe,我有一个PowerShell脚本,我在其中读取CSV文件,如果某列中的日期大于参数日期,我将该行输出到一个新文件 现在,我读取CSV文件,然后通过管道传输到ForEach对象,如果行“通过”,我将其存储在Arraylist中。然后,当处理完所有行后,我将Arraylist输出到一个输出CSV文件。我的起始CSV文件是225MB,超过25万行,这意味着这个过程很慢 是否有一种方法可以将过滤功能添加到管道中,以便只将传递的行一次性传递到输出CSV?当前的Where对象只使用了-比如,-包含。。。而不

我有一个PowerShell脚本,我在其中读取CSV文件,如果某列中的日期大于参数日期,我将该行输出到一个新文件

现在,我读取CSV文件,然后通过管道传输到
ForEach对象
,如果行“通过”,我将其存储在Arraylist中。然后,当处理完所有行后,我将Arraylist输出到一个输出CSV文件。我的起始CSV文件是225MB,超过25万行,这意味着这个过程很慢

是否有一种方法可以将过滤功能添加到管道中,以便只将传递的行一次性传递到输出CSV?当前的
Where对象
只使用了
-比如
-包含
。。。而不是更复杂的评估形式

对于最佳实践,我的代码如下:

Import-Csv -Delimiter "`t" -Header $headerCounter -Path $filePath |
    Select-Object  -Skip(1)  | 
    ForEach-Object {
        #Skip the header
        if( $lineCounter -eq 1)
        {
            return
        }

        $newDate = if ([string]::IsNullOrEmpty($_.1) -eq $true) 
                        { [DateTime]::MinValue } 
                        else { [datetime]::ParseExact($_.1,”yyyyMMdd”,$null) }

        $updateDate = if ([string]::IsNullOrEmpty($_.2) -eq $true) 
                        { [DateTime]::MinValue } 
                        else { [datetime]::ParseExact($_.2,”yyyyMMdd”,$null) }

        $distanceDate = (Get-Date).AddDays($daysBack * -1)

        if( $newDate -gt $distanceDate -or $updateDate -gt $distanceDate  )
        {
            [void]$filteredArrayList.Add($_)
        }
    }
    ...
    $filteredArrayList |
    ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | 
    select -Skip 1 |
    % { $_ -replace '"', ""} |
    out-file $ouputFile -fo -en unicode -Append

我添加了ConvertToDate作为一个函数,以避免混淆Where块

DistanceDate已过期,因为它似乎只计算一次

ExportCsv是一个将管道输入写入文件的小函数

我还没有测试过它,所以除非我走运,否则很可能会出现bug

function ConvertToDate {
    param(
        [String]$DateString
    )

    if ($DateString -eq '') {
        return [DateTime]::MinValue
    } else {
        return [DateTime]::ParseExact($DateString, ”yyyyMMdd”, $null)
    }
}

filter ExportCsv {
    param(
        [Parameter(Position = 1)]
        [String]$Path
    )

    $csv = $_ | ConvertTo-Csv -Delimiter "`t" | Select-Object -Last 1
    $csv -replace '"' | Out-File $Path -Append -Encoding Unicode -Force
}

$distanceDate = (Get-Date).AddDays($daysBack * -1)

Import-Csv -Delimiter "`t" -Header $headerCounter -Path $filePath |
    Select-Object  -Skip 1  |
    Where-Object { (ConvertToDate $_.1) -gt $distanceDate -or (ConvertToDate $_.2) -gt $distanceDate } |
    ExportCsv $OutputFile

当然,只需添加一个函数,该函数从管道中获取一个值,并将导入Csv的结果通过管道传递给它。在函数中,检查是否要筛选当前项。下面是一个简单的示例,它使用字符串列表并过滤以
h
开头的所有字符串:

$x = @('hello', 'world', 'hello', 'tree')


filter Filter-CsvByMyRequirements
{
    Param(
        [Parameter(Mandatory=$true, 
                   ValueFromPipeline=$true)]
        $InputObject
    )

    Process
    {
        if ($_ -match '^h.*')
        {
            $_
        }
    }
}


$x | Filter-CsvByMyRequirements | Write-Host
输出:

hello
hello

你的CSV文件看起来怎么样?你应该考虑把它变成一个实际的过滤器(其中过滤器是一个只实现进程块的函数)。它会更漂亮。@ChrisDent:我删除了Begin和End块,我的意思是,
filter-filter-CsvByMyRequirements{param(…),如果($-match'^h.*){$}
不知道的话。更改了它。ExportCsv函数无法立即运行,所以我只是在原始代码集中添加了csv创建代码。将“测试”代码放到另一个函数中非常有效。