En utilisant PowerShell, je veux remplacer toutes les occurrences exactes de [MYID]
dans un fichier donné par MyValue
. Quelle est la manière la plus simple de procéder?
powershell
amateur
la source
la source
Réponses:
Utilisation (version V3):
Ou pour V2:
la source
Notez que les parenthèses autour
(Get-Content file.txt)
sont obligatoires:la source
Set-Content
au lieu deOut-File
yuou vous obtenez un avertissement du type "Le processus ne peut pas accéder au fichier '123.csv' car il est utilisé par un autre processus." .Get-Content
parenthèses, cela fonctionne. Pouvez-vous expliquer dans votre réponse pourquoi la parenthèse est nécessaire? Je remplacerais encoreOut-File
avecSet-Content
parce qu'il est plus sûr; il vous protège contre l'effacement du fichier cible si vous oubliez la parenthèse.Set-Content
au lieu deOut-File
est une solution bien meilleure et plus sûre. Désolé d'avoir à voter.Je préfère utiliser la classe File de .NET et ses méthodes statiques comme le montre l'exemple suivant.
Cela a l'avantage de travailler avec une seule chaîne au lieu d'un tableau de chaînes comme avec Get-Content . Les méthodes prennent également en charge l'encodage du fichier ( BOM UTF-8 , etc.) sans que vous ayez à vous en préoccuper la plupart du temps.
De plus, les méthodes ne gâchent pas les fins de ligne (fins de ligne Unix qui pourraient être utilisées) contrairement à un algorithme utilisant Get-Content et passant par Set-Content .
Donc pour moi: moins de choses qui pourraient se briser au fil des ans.
Une chose peu connue lors de l'utilisation de classes .NET est que lorsque vous avez tapé "[System.IO.File] ::" dans la fenêtre PowerShell, vous pouvez appuyer sur la Tabtouche pour parcourir les méthodes.
la source
[System.IO.File] | gm
C:\Windows\System32\WindowsPowerShell\v1.0
?Celui ci-dessus ne fonctionne que pour "One File" uniquement, mais vous pouvez également l'exécuter pour plusieurs fichiers dans votre dossier:
la source
foreach
vous pouvez le faireGet-ChildItem 'C:\folder\file*.xml' -Recurse | ForEach { (Get-Content $_).Replace('[MYID]', 'MyValue') | Set-Content $_ }
foreach
, car Get-Content fait quelque chose que vous ne pourriez pas attendre ... Il renvoie un tableau de chaînes, où chaque chaîne est une ligne dans le fichier. Si vous parcourez un répertoire (et des sous-répertoires) qui se trouvent dans un emplacement différent de votre script en cours d'exécution, vous voudrez quelque chose comme ceci:Get-ChildItem $Directory -File -Recurse | ForEach { (Get-Content $_.FullName) | ForEach { $_ -replace '[MYID]', 'MyValue' } | Set-Content $_.FullName }
où$Directory
est le répertoire contenant les fichiers que vous souhaitez modifier.Vous pouvez essayer quelque chose comme ça:
la source
C'est ce que j'utilise, mais c'est lent sur les gros fichiers texte.
Si vous allez remplacer des chaînes dans des fichiers texte volumineux et que la vitesse est un problème, essayez d' utiliser System.IO.StreamReader et System.IO.StreamWriter .
(Le code ci-dessus n'a pas été testé.)
Il existe probablement une manière plus élégante d'utiliser StreamReader et StreamWriter pour remplacer du texte dans un document, mais cela devrait vous donner un bon point de départ.
la source
J'ai trouvé un moyen peu connu mais incroyablement cool de le faire à partir de Windows Powershell en action de Payette . Vous pouvez référencer des fichiers comme des variables, similaires à $ env: path, mais vous devez ajouter les accolades.
la source
$myFile
?$a = 'file.txt'; invoke-expression "`${c:$a} = `${c:$a} -replace 'oldvalue','newvalue'"
Si vous devez remplacer des chaînes dans plusieurs fichiers:
Il convient de noter que les différentes méthodes affichées ici peuvent être très différentes en ce qui concerne le temps qu'il faut pour terminer. Pour moi, j'ai régulièrement un grand nombre de petits fichiers. Pour tester ce qui est le plus performant, j'ai extrait 5,52 Go (5 933 604 999 octets) de XML dans 40 693 fichiers séparés et parcouru trois des réponses que j'ai trouvées ici:
la source
Crédit à @ rominator007
Je l'ai enveloppé dans une fonction (car vous voudrez peut-être l'utiliser à nouveau)
REMARQUE: ce n'est pas sensible à la casse !!!!!
Voir cet article: String.Replace ignoring case
la source
Cela a fonctionné pour moi en utilisant le répertoire de travail actuel dans PowerShell. Vous devez utiliser la
FullName
propriété, sinon elle ne fonctionnera pas dans PowerShell version 5. J'avais besoin de modifier la version cible du framework .NET dans TOUS mesCSPROJ
fichiers.la source
Un peu vieux et différent, car j'avais besoin de changer une certaine ligne dans toutes les instances d'un nom de fichier particulier.
De plus,
Set-Content
ne retournait pas de résultats cohérents, j'ai donc dû y recourirOut-File
.Code ci-dessous:
C'est ce qui a le mieux fonctionné pour moi sur cette version PowerShell:
la source
Petite correction pour la commande Set-Content. Si la chaîne recherchée n'est pas trouvée, la
Set-Content
commande vide (vide) le fichier cible.Vous pouvez d'abord vérifier si la chaîne que vous recherchez existe ou non. Sinon, il ne remplacera rien.
la source
set-content test.txt "hello hello world hello world hello"
, puis(get-content .\test.txt).Replace("something", "awesome") | set-content .\test.txt
ne videra pas le fichier comme suggéré dans ceci.