PowerShell plusieurs chaîne de remplacement de l'efficacité
Je suis en train de remplacer de 600 chaînes de caractères dans un texte très volumineux fichier de 30 mo+. Je suis l'actuel bâtiment d'un script qui fait cela; à la suite de cette Question:
Script:
$string = gc $filePath
$string | % {
$_ -replace 'something0','somethingelse0' `
-replace 'something1','somethingelse1' `
-replace 'something2','somethingelse2' `
-replace 'something3','somethingelse3' `
-replace 'something4','somethingelse4' `
-replace 'something5','somethingelse5' `
...
(600 More Lines...)
...
}
$string | ac "C:\log.txt"
Mais comme il s'agira de vérifier chaque ligne de 600 fois et il y a bien plus de 150 000+ lignes dans le fichier texte, cela signifie qu'il y a beaucoup de temps de traitement.
Est-il une meilleure solution que de faire ce qui est plus efficace?
Tous les conseils sur ce qui serait apprécié, Merci.
OriginalL'auteur Richard | 2013-07-17
Vous devez vous connecter pour publier un commentaire.
Donc, ce que vous dites, c'est que vous voulez remplacer tout de 600 chaînes dans chaque de 150 000 lignes, et que vous souhaitez exécuter une opération de remplacement par ligne?
Oui, il y a un moyen de le faire, mais pas dans PowerShell, au moins, je ne pense pas d'une. Il peut être réalisé en Perl.
La Méthode:
Le Problème:
Frustrant, PowerShell ne pas exposer le match variables en dehors de la regex pour remplacer appel. Il ne fonctionne pas avec le -remplacer opérateur et il ne fonctionne pas avec [regex]::remplacer.
En Perl, vous pouvez le faire, par exemple:
Cela va ajouter 5 pour les chiffres 1, 2, et 3 tout au long de la chaîne, de sorte que si la chaîne est "1224526123 [2] [6]", il se transforme en "6774576678 [7] [6]".
Cependant, dans PowerShell, ces deux échouer:
Dans les deux cas, $1 la valeur est null, et l'expression s'évalue à la plaine de vieux 5. Le match des variables dans les remplacements ne sont significatifs que dans la chaîne résultante, c'est à dire d'une seule chaîne de caractères entre guillemets ou quelle que soit la chaîne de caractères entre guillemets donne. Ils sont fondamentalement juste des références arrières qui ressemblent à des match de variables. Bien sûr, vous pouvez citer le $ avant de le nombre en une chaîne de caractères entre guillemets, de sorte qu'il permettra d'évaluer le correspondant match de groupe, mais cela va à l'encontre de l'objectif - il ne peut pas participer à une expression.
La Solution:
[Cette réponse a été modifiée à partir de l'original. Il a été mis en forme pour s'adapter correspondre les chaînes avec la regex métacaractères. Et l'écran de votre TÉLÉVISEUR, bien sûr.]
Si vous utilisez une autre langue est acceptable pour vous, le script Perl suivant fonctionne comme un charme:
Il recherche les clés de la table de hachage (à gauche de la =>), et les remplace par les valeurs correspondantes. Voici ce qui se passe:
BTW, vous pourriez avoir remarqué plusieurs autres modifications du script d'origine. Mon Perl a recueilli un peu de poussière au cours de mon récent PowerShell coup de pied, et sur un deuxième coup d'oeil, j'ai remarqué plusieurs choses qui pourraient être mieux fait.
while (<INPUT>)
lit le fichier ligne par ligne. Beaucoup plus sensible que la lecture de la totalité de 150 000 lignes dans un tableau, surtout si votre objectif est l'efficacité.@{[$replacements{$1}]}
à$replacements{$1}
. Perl n'est pas un moyen intégré de l'interpolation des expressions comme PowerShell est $(), donc @{[ ]} est utilisé comme une solution de contournement, - il crée un littéral de tableau d'un élément contenant l'expression. Mais j'ai réalisé qu'il n'est pas nécessaire si l'expression est juste une seule variable scalaire (j'ai eu là comme un vestige de mon premier essai, où j'étais en appliquant des calculs à la $1 match variable)."X:\Group_14\DACU"
avec la chaîne suivante"\\DACU$"
. J'ai essayé quelque chose comme ça'X:\Group_14\DACU' => '[\\DACU$]'
Mais il ne semble pas fonctionner, c'est de ma syntaxe est correcte?Ah, j'ai oublié le traitement des caractères spéciaux, comment bâclée. Le problème est que la barre oblique inverse est le caractère d'échappement en Perl (l'équivalent d'un backtick dans Powershell). Même si vous avez une seule cité de la chaîne, les problèmes s'ensuivent quand il est de passage dans une expression régulière, où la barre oblique désigne les différentes séquences d'échappement avec une signification particulière. Par exemple, \D signifie rien d'autre qu'un chiffre, et \G signifie que le décalage du dernier mondial de match sur la chaîne (ne vous inquiétez pas à ce sujet...). Je vais modifier la réponse de citer les clés de la table de hachage pour une utilisation dans une expression régulière.
OriginalL'auteur Adi Inbar
Combinant la technique de hachage à partir de Adi Inbar réponse, et le match de l'évaluateur de Keith Hill répondre à une autre question, ici, est de savoir comment vous pouvez effectuer le remplacer dans les PowerShell:
est un alias pour
ForEach-Object
(essayezGet-Alias foreach
). J'ai fait la mise à jour de l'exemple pour indiquer$matchEval
est un scriptblock.Intéressant...et déroutant...à propos de la 'foreach' alias. Merci pour le BULLETIN. Sera de $r.Remplacer le travail avec $matchEval comme un [scriptblock] quand il prend [Système.Texte.RegularExpressions.MatchEvaluator] tant que le deuxième paramètre? Même si elle le fait, ce dernier peut être plus utile.
OriginalL'auteur Emperor XLII
Je n'ai aucune idée de comment résoudre ce dans powershell, mais je ne sais comment le résoudre en Bash et c'est à l'aide d'un outil appelé le sed. Heureusement, il y a aussi Sed pour Windows. Si tout ce que vous voulez faire est de remplacer "quelque chose#" avec "somethingelse#" partout, alors cette commande va faire l'affaire pour vous
Dans Bash vous avais réellement besoin d'échapper à un couple de ces personnages, avec des barres obliques inverses, mais je ne suis pas sûr que vous avez besoin de windows. Si la première commande se plaint, vous pouvez essayer
OriginalL'auteur seanmk
Je voudrais utiliser le powershell instruction switch:
OriginalL'auteur Bill Barry