【问题标题】:Filter multiple CSV for text and create new files过滤多个 CSV 文本并创建新文件
【发布时间】: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还是只是一个文本文件而不关心字段和字段顺序?

标签: powershell 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")
    

    【讨论】:

      猜你喜欢
      • 2016-10-22
      • 1970-01-01
      • 1970-01-01
      • 2014-12-10
      • 2021-07-07
      • 2020-03-28
      • 2023-03-16
      • 2022-01-06
      • 2021-12-11
      相关资源
      最近更新 更多