Folosind PowerShell, vreau să înlocuiți toate exact aparițiile [MYID]
într-un fișier dat cu MyValue`. Ceea ce este cel mai simplu mod de a face acest lucru?
Utilizare (versiunea V3):
(Get-Content c:\temp\test.txt).replace('[MYID]', 'MyValue') | Set-Content c:\temp\test.txt
Sau pentru V2:
(Get-Content c:\temp\test.txt) -replace '\[MYID\]', 'MyValue' | Set-Content c:\temp\test.txt
(Get-Content file.txt) |
Foreach-Object {$_ -replace '\[MYID\]','MyValue'} |
Out-File file.txt
Notă în parantezele din jurul (Ia-Conținut file.txt)
este necesar:
Fără paranteze conținutul este citit, o linie la un moment dat, și curge pe conducte până când se ajunge-fișier sau set-conținut, care încearcă să scrie în același fișier, dar's deja deschis de conținut și veți obține o eroare. Paranteza determină funcționarea de lectură de conținut să fie efectuate o dată (deschide, citi și de aproape). Numai atunci când toate liniile au fost citite, ele sunt prin conducte la un moment dat și atunci când ajung la ultima comandă în conducte pot fi scrise la dosar. L's la fel ca $content=conținut; $content | unde ...
Prefer folosind File-clasa .NET și metode statice cum se vede în exemplul următor.
$content = [System.IO.File]::ReadAllText("c:\bla.txt").Replace("[MYID]","MyValue")
[System.IO.File]::WriteAllText("c:\bla.txt", $content)
Acest lucru are avantajul de a lucra cu un singur Șir în loc de un String-array și cu Get-Content. Metodele de asemenea, avea grijă de codificarea fișierului (UTF-8 LM, etc.) fără a fi nevoie pentru a avea grijă cel mai mult timp.
De asemenea, metodele don't strica capetele de linie (linie Unix finaluri care ar putea fi utilizate) în contrast cu un algoritm folosind Get-Conținut și conducte prin a Set-Conținut.
Asa ca pentru mine: mai Puține lucruri care ar putea rupe de-a lungul anilor.
Un pic de-cunoscute lucru atunci când se utilizează .NET clase este că, atunci când ați tastat în "[Sistem.IO.Fișier]::" în fereastra PowerShell puteți apăsa Fila cheie la pas prin metodele acolo.
Cea de mai sus se execută numai pentru "Un Fișier" numai, dar puteți rula, de asemenea, acest lucru pentru mai multe fișiere în folderul:
Get-ChildItem 'C:yourfile*.xml' -Recurse | ForEach {
(Get-Content $_ | ForEach { $_ -replace '[MYID]', 'MyValue' }) |
Set-Content $_
}
Aceasta este ceea ce am folosi, dar este lent pe fișiere text de mari dimensiuni.
get-content $pathToFile | % { $_ -replace $stringToReplace, $replaceWith } | set-content $pathToFile
Dacă aveți de gând să fi înlocuiți siruri de caractere în fișiere text de mari dimensiuni și viteza este un motiv de îngrijorare, uită-te în ajutorul Sistem.IO.StreamReader și Sistem.IO.StreamWriter.
try
{
$reader = [System.IO.StreamReader] $pathToFile
$data = $reader.ReadToEnd()
$reader.close()
}
finally
{
if ($reader -ne $null)
{
$reader.dispose()
}
}
$data = $data -replace $stringToReplace, $replaceWith
try
{
$writer = [System.IO.StreamWriter] $pathToFile
$writer.write($data)
$writer.close()
}
finally
{
if ($writer -ne $null)
{
$writer.dispose()
}
}
(Codul de mai sus nu a fost testat.)
Există, probabil, un mod mai elegant de a utiliza StreamReader si StreamWriter pentru înlocuirea textului într-un document, dar că ar trebui să vă dau un bun punct de plecare.
De Credit a @rominator007
L-am înfășurat într-o funcție (pentru că poate doriți să-l folosească din nou)
function Replace-AllStringsInFile($SearchString,$ReplaceString,$FullPathToFile)
{
$content = [System.IO.File]::ReadAllText("$FullPathToFile").Replace("$SearchString","$ReplaceString")
[System.IO.File]::WriteAllText("$FullPathToFile", $content)
}
NOTĂ: Aceasta NU este case sensitive!!!!!
Vezi acest post: https://stackoverflow.com/questions/6275980/string-replace-ignoring-case
Am găsit-o puțin cunoscute, dar extraordinar de misto mod de a face din Payette's Windows Powershell în Acțiune. Puteți de referință fișierele, cum ar fi variabile, similare cu $env:calea, dar ai nevoie pentru a adăuga acolade.
${c:file.txt} = ${c:file.txt} -replace 'oldvalue','newvalue'
Aceasta a lucrat pentru mine, folosind directorul curent de lucru în PowerShell. Ai nevoie de a utiliza FullName de proprietate, sau nu o't de muncă în PowerShell versiunea 5. Am nevoie pentru a schimba obiectivul .NET framework versiunea în TOATE
CSPROJ` files.
gci -Recurse -Filter *.csproj |
% { (get-content "$($_.FullName)")
.Replace('<TargetFramework>net47</TargetFramework>', '<TargetFramework>net462</TargetFramework>') |
Set-Content "$($_.FullName)"}
Un pic vechi și diferite, ca am nevoie pentru a schimba o anumită linie în toate cazurile de un anumit nume de fișier.
De asemenea, Set-Conținutnu a fost revenirea rezultate consistente, așa că a trebuit să recurgă la Dosar
.
Codul de mai jos:
$FileName =''
$OldLine = ''
$NewLine = ''
$Drives = Get-PSDrive -PSProvider FileSystem
foreach ($Drive in $Drives) {
Push-Location $Drive.Root
Get-ChildItem -Filter "$FileName" -Recurse | ForEach {
(Get-Content $_.FullName).Replace($OldLine, $NewLine) | Out-File $_.FullName
}
Pop-Location
}
Aceasta este ceea ce a lucrat cel mai bine pentru mine pe acest PowerShell versiune:
Maior.Minore.Construi.Revizuirea
5.1.16299.98
Mică corecție pentru Conținutul de comandă. Dacă șirul căutat nu este găsit Set-Conținut comandă va blank (gol) fișierul țintă.
Puteți să verificați mai întâi dacă șirul sunteți în căutarea pentru mai existe sau nu. Dacă nu-l va înlocui nimic.
If (select-string -path "c:\Windows\System32\drivers\etc\hosts" -pattern "String to look for") `
{(Get-Content c:\Windows\System32\drivers\etc\hosts).replace('String to look for', 'String to replace with') | Set-Content c:\Windows\System32\drivers\etc\hosts}
Else{"Nothing happened"}