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