过滤多个 CSV 文本并创建新文件

Posted

技术标签:

【中文标题】过滤多个 CSV 文本并创建新文件【英文标题】:Filter multiple CSV for text and create new files 【发布时间】:2020-05-29 11:35:09 【问题描述】:

我有大约 2500 个 CSV 文件,每个文件大小约为 20MB。我正在尝试从每个文件中过滤掉某些行并将其保存到一个新文件中。

所以,如果我有:

File 1 :
    Row1
    Row2
    Row3
File 2 : 
    Row2
    Row3 
and so on..

如果我过滤所有文件并选择“Row2”作为过滤文本,则新文件夹应该包含所有文件,其中只有与过滤文本匹配的行。

浏览一些论坛,我想出了以下可能有助于我过滤行的方法,但我不确定如何递归地执行此操作,而且我也不知道这是否是一种足够快的方法。任何帮助表示赞赏。

Get-Content "C:\Path to file" | Where$_ -match "Rowfiltertext*" | Out-File "Path to Out file"

我使用的是 Windows,所以我猜 Powershell 类型的解决方案在这里是最好的。

要过滤的文本将始终位于第一列。

谢谢 悉达特

【问题讨论】:

如何选择要删除的行?搜索模式可以是行中的任何内容,还是应该是特定列中的值? Select-String cmdlet 和switch 结构都可以加载文件...并快速完成。两者都可以处理正则表达式模式。我会尝试其中一个... [grin] @Theo :要过滤的文本将始终位于第一列。也使用此信息更新了问题。 还有一些问题:[1]所有 csv 文件都有完全相同的标题/字段吗? [2]输出文件也应该是带有标题的csv还是只是一个文本文件而不关心字段和字段顺序? 【参考方案1】:

以下是在(文本)文件中搜索字符串的两种快速方法:

1) 使用开关

$searchPattern = [regex]::Escape('Rowfiltertext')  # for safety escape regex special characters
$sourcePath    = 'X:\Path\To\The\Csv\Files'
$outputPath    = 'X:\FilteredCsv.txt'

# if you also need to search inside subfolders, append -Recurse to the Get-ChildItem cmdlet
Get-ChildItem -Path $sourcePath -Filter '*.csv' -File | ForEach-Object 
    # iterate through the lines in the file and output the ones that match the search pattern
    switch -Regex -File $_.FullName 
        $searchPattern  $_ 
    
 | Set-Content -Path $outputPath  # add -PassThru to also show on screen

2) 使用 Select-String

$searchPattern = [regex]::Escape('Rowfiltertext')  # for safety escape regex special characters
$sourcePath    = 'X:\Path\To\The\Csv\Files'
$outputPath    = 'X:\FilteredCsv.txt'

# if you also need to search inside subfolders, append -Recurse to the Get-ChildItem cmdlet
Get-ChildItem  -Path $sourcePath -Filter '*.csv' -File | ForEach-Object 
    ($_ | Select-String -Pattern $searchPattern).Line
 | Set-Content -Path $outputPath  # add -PassThru to also show on screen

如果您想为每个原始文件输出一个新的 csv 文件,

使用:

3) 使用开关

$searchPattern = [regex]::Escape('Rowfiltertext')  # for safety escape regex special characters
$sourcePath    = 'X:\Path\To\The\Csv\Files'
$outputPath    = 'X:\FilteredCsv'

if (!(Test-Path -Path $outputPath -PathType Container)) 
    $null = New-Item -Path $outputPath -ItemType Directory


# if you also need to search inside subfolders, append -Recurse to the Get-ChildItem cmdlet
(Get-ChildItem -Path $sourcePath -Filter '*.csv' -File) | ForEach-Object 
    # create a full target filename for the filtered output csv
    $outFile = Join-Path -Path $outputPath -ChildPath ('New_0' -f $_.Name)
    # iterate through the lines in the file and output the ones that match the search pattern
    $result = switch -Regex -File $_.FullName 
        $searchPattern  $_ 
    
    $result | Set-Content -Path $outFile  # add -PassThru to also show on screen

4) 使用 Select-String

$searchPattern = [regex]::Escape('Rowfiltertext')  # for safety escape regex special characters
$sourcePath    = 'X:\Path\To\The\Csv\Files'
$outputPath    = 'X:\FilteredCsv'

# if you also need to search inside subfolders, append -Recurse to the Get-ChildItem cmdlet
(Get-ChildItem  -Path $sourcePath -Filter '*.csv' -File) | ForEach-Object 
    # create a full target filename for the filtered output csv
    $outFile = Join-Path -Path $outputPath -ChildPath ('New_0' -f $_.Name)
    ($_ | Select-String -Pattern $searchPattern).Line | Set-Content -Path $outFile  # add -PassThru to also show on screen

希望有帮助

【讨论】:

【参考方案2】:

回复。 “足够快的方法”: Get-Content 非常慢。 您可以改用“System.IO.StreamReader”,即将完整的文件内容读入一个字符串,然后将该字符串拆分成行等等,例如:

[System.IO.FileStream]$objFileStream = New-Object System.IO.FileStream($Csv.FullName, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
[System.IO.StreamReader]$objStreamReader = New-Object System.IO.StreamReader($objFileStream, [System.Text.Encoding]::UTF8)
$strFileContent = ($objStreamReader.ReadToEnd())
$objStreamReader.Close()
$objStreamReader.Dispose()
$objFileStream.Close()
$objFileStream.Dispose()

[string[]]$arrFileContent = $strFileContent -split("`r`n")

【讨论】:

以上是关于过滤多个 CSV 文本并创建新文件的主要内容,如果未能解决你的问题,请参考以下文章

在包含大数据的csv文件上创建用户输入过滤器

java 8流多个过滤器

scala过滤操作过滤CSV文件

pandas read_csv 和使用 usecols 过滤列

使用 Java 从 CSV 文件中过滤掉数字

如何通过java过滤文本文件并将结果保存到新文件中