Mit PowerShell möchte ich alle genauen Vorkommen [MYID]
in einer bestimmten Datei durch ersetzen MyValue
. Was ist der einfachste Weg, dies zu tun?
powershell
Amateur
quelle
quelle
Antworten:
Verwendung (V3-Version):
Oder für V2:
quelle
Beachten Sie, dass die Klammern
(Get-Content file.txt)
erforderlich sind:quelle
Set-Content
anstelle von "Out-File
Sie erhalten eine Warnung wie " Der Prozess kann nicht auf die Datei '123.csv' zugreifen, da sie von einem anderen Prozess verwendet wird. " .Get-Content
in Klammern funktioniert es. Können Sie in Ihrer Antwort erklären, warum die Klammer notwendig ist? Ich würde immer noch ersetzenOut-File
mit ,Set-Content
weil es sicherer ist ; Es schützt Sie vor dem Löschen der Zieldatei, wenn Sie die Klammer vergessen.Set-Content
stattOut-File
ist eine viel bessere und sicherere Lösung. Entschuldigung, ich muss abstimmen.Ich bevorzuge die Verwendung der File-Klasse von .NET und ihrer statischen Methoden, wie im folgenden Beispiel gezeigt.
Dies hat den Vorteil, dass mit einem einzelnen String anstelle eines String-Arrays wie bei Get-Content gearbeitet wird . Die Methoden kümmern sich auch um die Codierung der Datei (UTF-8- Stückliste usw.), ohne dass Sie sich die meiste Zeit darum kümmern müssen.
Außerdem bringen die Methoden die Zeilenenden (möglicherweise verwendete Unix-Zeilenenden) nicht durcheinander, im Gegensatz zu einem Algorithmus, der Get-Content verwendet und zu Set-Content weiterleitet .
Also für mich: Weniger Dinge, die im Laufe der Jahre kaputt gehen könnten.
Bei der Verwendung von .NET-Klassen ist wenig bekannt, dass Sie nach Eingabe von "[System.IO.File] ::" im PowerShell-Fenster die TabTaste drücken können, um die dortigen Methoden zu durchlaufen.
quelle
[System.IO.File] | gm
C:\Windows\System32\WindowsPowerShell\v1.0
?Die obige Version wird nur für "Eine Datei" ausgeführt. Sie können sie jedoch auch für mehrere Dateien in Ihrem Ordner ausführen:
quelle
foreach
können Sie dies tunGet-ChildItem 'C:\folder\file*.xml' -Recurse | ForEach { (Get-Content $_).Replace('[MYID]', 'MyValue') | Set-Content $_ }
foreach
, weil Get-Content etwas tut, was Sie vielleicht nicht erwarten ... Es gibt ein Array von Zeichenfolgen zurück, wobei jede Zeichenfolge eine Zeile in der Datei ist. Wenn Sie ein Verzeichnis (und Unterverzeichnisse) durchlaufen, die sich an einem anderen Speicherort als Ihr ausgeführtes Skript befinden, möchten Sie Folgendes:Get-ChildItem $Directory -File -Recurse | ForEach { (Get-Content $_.FullName) | ForEach { $_ -replace '[MYID]', 'MyValue' } | Set-Content $_.FullName }
Wo$Directory
befindet sich das Verzeichnis mit den Dateien, die Sie ändern möchten?Sie könnten so etwas versuchen:
quelle
Dies ist, was ich benutze, aber es ist langsam bei großen Textdateien.
Wenn Sie Zeichenfolgen in großen Textdateien ersetzen möchten und die Geschwindigkeit ein Problem darstellt , sollten Sie System.IO.StreamReader und System.IO.StreamWriter verwenden .
(Der obige Code wurde nicht getestet.)
Es gibt wahrscheinlich eine elegantere Möglichkeit, StreamReader und StreamWriter zum Ersetzen von Text in einem Dokument zu verwenden, aber das sollte Ihnen einen guten Ausgangspunkt bieten.
quelle
Ich fand eine wenig bekannte, aber erstaunlich coole Möglichkeit, dies mit Payettes Windows Powershell in Action zu tun . Sie können auf Dateien wie Variablen verweisen, ähnlich wie bei $ env: path, aber Sie müssen die geschweiften Klammern hinzufügen.
quelle
$myFile
.$a = 'file.txt'; invoke-expression "`${c:$a} = `${c:$a} -replace 'oldvalue','newvalue'"
Wenn Sie Zeichenfolgen in mehreren Dateien ersetzen müssen:
Es sollte beachtet werden, dass die verschiedenen hier veröffentlichten Methoden in Bezug auf die Zeit, die für die Fertigstellung benötigt wird, sehr unterschiedlich sein können. Für mich habe ich regelmäßig eine große Anzahl kleiner Dateien. Um zu testen, was am leistungsfähigsten ist, habe ich 5,52 GB (5.933.604.999 Byte) XML in 40.693 separaten Dateien extrahiert und drei der hier gefundenen Antworten durchgearbeitet:
quelle
Gutschrift an @ rominator007
Ich habe es in eine Funktion eingewickelt (weil Sie es möglicherweise wieder verwenden möchten)
HINWEIS: Hierbei wird NICHT zwischen Groß- und Kleinschreibung unterschieden !!!!!
Siehe diesen Beitrag: String.Replace Ignorieren von Groß- und Kleinschreibung
quelle
Dies funktionierte bei mir mit dem aktuellen Arbeitsverzeichnis in PowerShell. Sie müssen die
FullName
Eigenschaft verwenden, sonst funktioniert sie in PowerShell Version 5 nicht. Ich musste die .NET Framework-Zielversion in ALLEN meinenCSPROJ
Dateien ändern .quelle
Ein bisschen alt und anders, da ich in allen Fällen eines bestimmten Dateinamens eine bestimmte Zeile ändern musste.
Außerdem wurden
Set-Content
keine konsistenten Ergebnisse zurückgegeben, sodass ich darauf zurückgreifen mussteOut-File
.Code unten:
Folgendes hat bei dieser PowerShell-Version am besten funktioniert:
quelle
Kleine Korrektur für den Befehl Set-Content. Wenn die gesuchte Zeichenfolge nicht gefunden
Set-Content
wird, wird die Zieldatei durch den Befehl leer (leer).Sie können zunächst überprüfen, ob die gesuchte Zeichenfolge vorhanden ist oder nicht. Wenn nicht, wird nichts ersetzt.
quelle
set-content test.txt "hello hello world hello world hello"
und leert dann(get-content .\test.txt).Replace("something", "awesome") | set-content .\test.txt
die Datei nicht wie hier vorgeschlagen.