Question

J'ai un fichier qui ressemble à ceci:
a, 1
b, 2
c, 3
a, 4
b, 5
c, 6
(... 1,000s de répétition de lignes)

Comment puis-je transposer dans ce
a, b, c
1,2,3
4,5,6

Merci

Était-ce utile?

La solution

Voici une force brute d'un paquebot de l'enfer qui le fera:

PS> Get-Content foo.txt | 
      Foreach -Begin {$names=@();$values=@();$hdr=$false;$OFS=',';
                      function output { if (!$hdr) {"$names"; $global:hdr=$true}
                                        "$values";
                                        $global:names=@();$global:values=@()}} 
              -Process {$n,$v = $_ -split ',';
                        if ($names -contains $n) {output};
                        $names+=$n; $values+=$v } 
              -End {output}
a,b,c
1,2,3
4,5,6

Il est pas ce que je qualifierais élégant mais si vous vous en tirer. Cela devrait copier / coller correctement en l'état. Toutefois, si vous reformater à ce qui est indiqué ci-dessus, vous aurez besoin: Reporte-tiques après la dernière bouclés sur les deux scriptblocks Begin et processus. Ce script nécessite PowerShell 2.0 car il repose sur le nouvel opérateur -split.

Cette approche permet une utilisation intensive de la cmdlet Foreach-Object. Normalement, lorsque vous utilisez Foreach-Object (alias est Foreach) dans le pipeline vous suffit de spécifier un scriptblock comme ceci:

Get-Process | Foreach {$_.HandleCount}

qui affiche le nombre de handles pour chaque processus. Cette utilisation de Foreach-Object utilise le scriptblock -process implicitement ce qui signifie qu'il exécute une fois pour chaque objet qu'il reçoit du pipeline. Maintenant, si nous voulons totaliser toutes les poignées pour chaque processus? Ignorer le fait que vous pouvez simplement utiliser Measure-Object HandleCount -Sum pour ce faire, je vais vous montrer comment Foreach-Object peut le faire. Comme vous le voyez dans la solution originale à ce problème, Foreach peut prendre les deux Begin scriptblock qui est exécutée une fois pour le premier objet dans la canalisation et un scripblock End qui exécute quand il n'y a plus d'objets dans le pipeline. Voici comment vous pouvez totaliser le nombre de poignée à l'aide Foreach-Object:

gps | Foreach -Begin {$sum=0} -Process {$sum += $_.HandleCount } -End {$sum}

relative ce retour à la solution du problème, dans Begin scriptblock j'initialiser certaines variables pour tenir le tableau des noms et des valeurs ainsi qu'un bool (hdr $) qui me dit si oui ou non l'en-tête a été sortie (nous ne veulent sortie une fois). La prochaine chose mind légèrement souffle est que je déclare également une fonction (sortie) dans Begin scriptblock que j'appelle à la fois le processus et de fin scriptblocks à la sortie de l'ensemble actuel des données stockées dans les noms $ et des valeurs $.

La seule autre astuce est que le scriptblock Process utilise l'opérateur -contains pour voir si le nom du champ de la ligne actuelle a déjà été vu auparavant. Si oui, alors la sortie les noms et les valeurs et de réinitialiser les tableaux à vide. Sinon juste Stash le nom et la valeur dans les tableaux appropriés afin qu'ils puissent être sauvés plus tard.

BTW la raison pour laquelle la fonction de sortie doit utiliser le global: spécificateur sur les variables est que PowerShell effectue une approche « copy-on-write » lorsqu'un champ imbriqué modifie une variable définie en dehors de son champ d'application. Cependant, lorsque nous voulons vraiment que la modification de se produire à la portée plus élevée, il faut dire que PowerShell en utilisant un modificateur comme global: ou d'un script.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top