过滤多个 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 文本并创建新文件的主要内容,如果未能解决你的问题,请参考以下文章