Je veux trouver un morceau de texte dans un grand fichier XML et souhaitez remplacer un autre texte. La taille du fichier est autour (50 Go). Je veux faire cela dans la ligne de commande. Je regarde PowerShell et je veux savoir s'il peut gérer la grande taille. De plus, je voudrais savoir la syntaxe pour échapper aux opérateurs clés de PowerShell. Je suis un PowerShell Newbie
Actuellement, j'essaie actuellement quelque chose comme ça, mais cela ne l'aime pas p> Le texte que je veux remplacer est xmlns: xsi = "http://www.w3.org/2001/xmlschema-Instance" strong> avec chaîne vide "". p> questions p> merci p> p>
5 Réponses :
Cela ne l'aime pas parce que vous ne pouvez pas lire à partir d'un fichier et en écriture en même temps en utilisant le contenu de get-contenu / set. Je recommande d'utiliser un fichier Temp, puis à la fin, renommez FILE1.XML vers File1.xml.bak et renommez le fichier Temp to File1.xml. P>
. \ Myscript.ps1 code> et s'il utilise des paramètres, alors c: \ users \ joe \ myscript.ps1 c: \ temp \ file1.xml < / code>. li>
-
En général pour les regextes, je voudrais utiliser des guillemets simples si vous n'avez pas besoin de référencer des variables PowerShell. Ensuite, il vous suffit de vous soucier de l'évacuation de Regex et de ne pas trop s'échapper de PowerShell. Si vous avez besoin d'utiliser des guillemets, le caractère de la coche arrière est le caractère d'évacuation en double guilleme. "` $ p1 est défini sur $ PS1 ". Dans votre exemple, la citation unique simplifie votre regex à (Remarque: Les barres obliques ne sont pas des métacaracteurs dans Regex): P>
'xmlns: xsi = "http://www.w3.org/2001/xmlschema-Instance"' p> li>
-
Vous voulez absolument diffuser cela puisque 50GB ne s'intègre pas dans la mémoire. Cependant, cela pose un problème si vous traitez la ligne de ligne. Et si le texte que vous souhaitez remplacer est divisé sur plusieurs lignes? P> li>
- Si vous n'avez pas le problème de la ligne de scission, je pense que PowerShell peut gérer cela. Li>
ol>
@Keith, vous faites vraiment confiance à PowerShell;) Je m'inquiéterais peut-être de OutofMemoryException car 50 Go est assez grand pour collecter de petites fuites de mémoire .. Juste une supposition. Personnellement, j'utiliserais directement fichier.open code> et travaillez avec un flux et comparez manuellement (pas de regex).
Et ne devrait-on pas utiliser une sorte d'API XML pour faire cela? Juste une pensée. Dunno si SAX ou Stax sont disponibles dans .NET; Je travaille trop rarement avec XML, mais une chaîne remplacer les sons ne va pas pour cela.
.NET dispose d'un lecteur de style de curseur en avant (xmlreader / xmltextreader) - un mécanisme de traction qui est un peu différent de l'approche Push Sax. C'est un peu fastidieux mais un bon moyen d'aller lorsque tout le document XML ne s'intègre pas dans la mémoire.
@stej, bon point sur la regex - ne semble pas l'air nécessaire et pourrait être remplacé par une chaîne.replace ().
Le caractère d'échappement dans les chaînes PowerShell est le backttick (`), pas la barre oblique inverse (\). Je donnerais un exemple, mais le backtick est également utilisé par le marquage Wiki. : ( p>
La seule chose que vous devriez avoir à vous échapper est les citations - les périodes et telles devraient être correctes sans. P>
J'ai eu un besoin similaire (et un manque similaire d'expérience PowerShell), mais j'ai cobblé une réponse complète des autres réponses sur cette page plus un peu plus de recherches.
Je voulais aussi éviter le traitement des regex, puisque je ne voulais pas Il en a besoin - juste une simple chaîne remplacer - mais sur un fichier volumineux, je ne le voulais donc pas chargé dans la mémoire. P>
Voici la commande que j'ai utilisée (ajout de lisibilités pour la lisibilité): P>
Get-Content sourcefile.txt
| Foreach-Object {$_.Replace('http://example.com', 'http://another.example.com')}
| Set-Content result.txt
Sur un fichier PS de 200 Mo a pris 3,5 Go de RAM. 30% de CPU quand je l'ai tué.
peut-être vérifier -readcount b> ou -raw b> HAPYSYSADM.COM/2014/10/...
Ceci est ma prise, construisant certaines des autres réponses ici: et appelé comme si: p>
En plus de vous inquiéter de la lecture du fichier dans des morceaux pour éviter de le charger en mémoire, vous devez jeter un disque si vous ne stockez pas le contenu total du fichier résultant en mémoire.
Get-Content sourcefile.txt -ReadCount 10000 |
Foreach-Object {
$line = $_.Replace('http://example.com', 'http://another.example.com')
Add-Content -Path result.txt -Value $line
}
Compte tenu de la valeur par défaut de ReadCount comme 1, est-ce une amélioration? Certains fichiers contiennent tout sur une ligne (telle que JSON minimisé).
@Duck_Tape_coder, je me sens comme ça dépendrait de la rapidité de la vitesse. Je vais faire des tests et mettre à jour la réponse si vous enlevez / la modification du nombre de lecture a un meilleur effet. Je vais aussi regarder dans d'autres options que j'ai conscientes depuis que j'ai posté cette réponse.