0

我有一个包含 CampaignNames 和 ID 的文件。这两个字段由管道分隔|。ID 由空格分隔。我想查找文件中的所有行(索普þ包含 ID 的文件(thorpe 分隔)中查找所有行,并将这些行输出到每个名称的单独文件中。该文件通常为 4-7 GB,有时更大。

campaigns.txt

姓名|姓名ID
名字|123 212 445 39
第二名|313 939
第三名|219

数据标识文件:

日期þIDþ代码
10-22-14+123+Abc
10-24-16+212+战俘
09-18-15+219

所以我想要创建 3 个文件。FirstName.txt包含 2 行。SecondName.txt包含 0 行。 ThirdName.txt包含 1 行。

我拼凑了来自各种来源的一些代码并想出了这个。但是,我想知道是否有比多次读取数据文件更好的方法。有什么想法吗?

$campaigns = Import-Csv "campaigns.txt" -Delimiter "|"
$datafile = "5282_10-19-2016"
$encoding = [Text.Encoding]::GetEncoding('iso-8859-1')

echo "Starting.."
Get-Date -Format g

foreach ($campaign in $campaigns) {
    $campaignname = $campaign.CampaignName
    $campaignids = $campaign.CampaignID.split(" ")
    echo "Looking for $campaignname - $campaignids"
    $writer = New-Object System.IO.StreamWriter($campaignname + "_filtered.txt")
    foreach ($campaignid in $campaignids) {
        $datareader = New-Object System.IO.StreamReader($datafile, $encoding)
        while ($dataline = $datareader.ReadLine()) {
            if ($dataline -match $campaignid) {
                $data = $dataline.Split("þ")
                $writer.WriteLine('{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}', $data[0], $data[3], $data[5], $data[8], $data[12], $data[14], $data[19], $data[20])
            }
        }
    }
    $writer.Close()
}

echo "Done!"
Get-Date -Format g
4

2 回答 2

1

只需处理一次巨大的数据文件。
从由campaign.txt 构建的哈希表中选择广告系列名称。
假设没有多少活动(例如,少于 1000 个)写入尽可能多的 StreamWriter。

$campaignByID = @{}
foreach ($c in (Import-Csv 'campaigns.txt' -Delimiter '|')) {
    foreach ($id in ($c.CampaignID -split ' ')) {
        $campaignByID[$id] = $c.CampaignName
    }
}

$campaignWriters = @{}
$datareader = New-Object IO.StreamReader($datafile, $encoding)
while (!$datareader.EndOfStream) {
    $data = $datareader.ReadLine().Split('þ')
    $campaignName = $campaignByID[$data[1]]
    if ($campaignName) {
        $writer = $campaignWriters[$campaignName]
        if (!$writer) {
            $writer = $campaignWriters[$campaignName] =
                New-Object IO.StreamWriter($campaignName + '_filtered.txt')
        }
        $writer.WriteLine(($data[0,3,5,8,12,14,19,20] -join '|'))
    }
}

$datareader.Close()
foreach ($writer in $campaignWriters.Values) {
    $writer.Close()
}

要显示Write-Progress基于$datareader.BaseStream.Position / $datareader.BaseStream.Length * 100但不要为每个数据文件行执行的进度,因为它会减慢处理速度,请每 1 秒执行一次,例如,使用 datetime 变量:在一秒过去后更新它并显示进度.

于 2016-10-23T03:36:45.920 回答
-1

尝试这个 ;)

   $campaigns=import-csv C:\temp\campaigns.txt -Delimiter "|"
   $datafile=import-csv C:\temp\5282_10-19-2016.txt  -Delimiter "þ"  -Encoding Default
   $DirResult="C:\temp\root"

   $campaigns | %{ foreach ($item in ($_.NameID.Split(" "))) {New-Object PSObject -Property @{  Name=$_.Name ; ValID=$item} } } | %{ $datafile | where id -eq $_.ValID | export-csv -Append -Delimiter "|" -Path ("$dirresult\" + $_.ValID + "_filtered.txt") -NoTypeInformation }
于 2016-10-23T11:11:33.483 回答