2016-10-23 42 views
0

我有一個包含CampaignNames和IDs的文件。這兩個字段由管道|分隔。這些ID由空格分隔。我想查找包含ID的文件(分隔的thorpe þ)中的所有行,並將這些行輸出到每個名稱的單獨文件中。這個文件通常是4-7 GB,有時更大。在另一個文件中查找字符串並輸出某些列

campaigns.txt

Name|NameID 
FirstName|123 212 445 39 
SecondName|313 939 
ThirdName|219

數據ID文件:

DateþIDþCode 
10-22-14þ123þAbc 
10-24-16þ212þPow 
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 

回答

1

只處理一次巨大的數據文件。
從由campaign.txt構建的散列表中選擇廣告系列名稱。
假設沒有太多的活動(比如少於1000個)寫入儘可能多的StreamWriters。

$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() 
} 

顯示基於$datareader.BaseStream.Position/$datareader.BaseStream.Length * 100進度使用Write-Progress,但並不適用於所有數據文件行這樣做,因爲它會處理慢下來,做到每1秒,例如,使用日期時間變量:更新當一秒鐘過去並顯示進度。

+0

哇,這降低了處理時間從一個小時到20分鐘爲一個4GB的文件。謝謝! – Esuriency

-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 } 
+1

其實,不要試試這個。 'Import-Csv'開始時很慢,但是將幾千兆字節的數據文件讀入內存只是一個壞建議。該系統很可能會放慢抓取速度,因爲它開始交換。 –

相關問題