2016-10-23 2 views
0

J'ai un fichier contenant CampaignNames et ID. Les deux champs sont séparés par un tuyau |. Les ID sont séparés par un espace. Je veux trouver toutes les lignes dans un fichier (thorpe þ délimité) qui contiennent les ID, et la sortie de ces lignes dans des fichiers séparés par nom. Ce fichier est généralement de 4 à 7 Go, parfois plus volumineux.Recherche de chaînes dans un fichier dans un autre et sortie de certaines colonnes

campaigns.txt:

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

ID de données Fichier:

DateþIDþCode 
10-22-14þ123þAbc 
10-24-16þ212þPow 
09-18-15þ219

Je ne voudrais donc 3 fichiers créés. FirstName.txt contient 2 lignes. SecondName.txt contient 0 lignes. ThirdName.txt contient 1 ligne.

J'ai concocté du code provenant de diverses sources et j'ai trouvé cela. Cependant, je me demande s'il y a une meilleure façon que d'avoir à lire le fichier de données plusieurs fois. Des pensées là-bas?

$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 

Répondre

1

Traitez l'énorme fichier de données une seule fois.
Sélectionnez les noms de campagnes à partir d'une table de hachage créée à partir de campaign.txt.
En supposant qu'il n'y ait pas beaucoup de campagnes (disons moins de 1000) écrivent à autant de 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() 
} 

Pour afficher l'utilisation du progrès Write-Progress basé sur $datareader.BaseStream.Position/$datareader.BaseStream.Length * 100 mais ne le font pas pour chaque ligne datafile parce que ça va ralentir le traitement, faire toutes les 1 seconde, par exemple, en utilisant une variable datetime: mettre à jour quand une seconde s'est écoulée et affiche la progression.

+0

Wow cela a eu le temps d'arrêt de traitement d'une heure à 20 minutes pour un fichier de 4 Go. Je vous remercie! – Esuriency

-1

essayer cela;)

$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

En fait, ne l'essayez pas. 'Import-Csv' est lent au début, mais lire un fichier de données de plusieurs gigaoctets en mémoire est juste un mauvais conseil. Le système ralentira très probablement vers une analyse car il commence à échanger. –