Как заменить каждое вхождение строки в файле PowerShell?
используя PowerShell, я хочу заменить все точные вхождения [MYID]
в данном файле с MyValue
. Как это сделать проще всего?
11 ответов
использование (версия V3):
(Get-Content c:\temp\test.txt).replace('[MYID]', 'MyValue') | Set-Content c:\temp\test.txt
или для 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
обратите внимание на круглые скобки вокруг (Get-Content file.txt)
требуется:
без скобок содержимое считывается, по одной строке за раз, и течет вниз по конвейеру, пока не достигнет-file или set-content, который пытается записать в тот же файл, но он уже открыт get-content, и вы получаете ошибку. В скобках операция чтения содержимого выполняется один раз (открыть, прочитать и закрыть). Только тогда, когда все строки были прочитаны, они передаются по одному время и когда они достигают последней команды в конвейере они могут быть записаны в файл. Это то же самое, что $content=content; $content | where ...
Я предпочитаю использовать файл-класс .NET и его статические методы, как показано в следующем примере.
$content = [System.IO.File]::ReadAllText("c:\bla.txt").Replace("[MYID]","MyValue")
[System.IO.File]::WriteAllText("c:\bla.txt", $content)
это имеет преимущество работы с одной строкой вместо строкового массива, как с Get-Content. Методы также позаботятся о кодировке файла (UTF-8 BOM, etc. без того, чтобы большую часть времени заботиться о тебе.
также методы не испортят окончания строк (Unix-окончания строк, которые могут быть использованы) в контраст с алгоритмом, использующим Get-Content и piping through to Set-Content.
Итак, для меня: меньше вещей, которые могут сломаться за эти годы.
малоизвестная вещь при использовании классов .NET заключается в том, что когда вы ввели "[System.ИО.File]:: "в окне PowerShell вы можете нажать Tab ключ к шагу через методы.
один выше работает только для "одного файла", но вы также можете запустить это для нескольких файлов в вашей папке:
Get-ChildItem 'C:yourfile*.xml' -Recurse | ForEach {
(Get-Content $_ | ForEach { $_ -replace '[MYID]', 'MyValue' }) |
Set-Content $_
}
вы можете попробовать что-то вроде этого:
$path = "C:\testFile.txt"
$word = "searchword"
$replacement = "ReplacementText"
$text = get-content $path
$newText = $text -replace $word,$replacement
$newText > $path
это то, что я использую, но это медленно для больших текстовых файлов.
get-content $pathToFile | % { $_ -replace $stringToReplace, $replaceWith } | set-content $pathToFile
Если вы собираетесь заменить строки в больших текстовых файлов и скорость, рассмотреть возможность использования
Это сработало для меня, используя текущий рабочий каталог в PowerShell. Вам нужно использовать FullName
свойство, или оно не будет работать в PowerShell версии 5. Мне нужно было изменить целевую версию .NET framework во всех моих CSPROJ
файлы.
gci -Recurse -Filter *.csproj |
% { (get-content "$($_.FullName)")
.Replace('<TargetFramework>net47</TargetFramework>', '<TargetFramework>net462</TargetFramework>') |
Set-Content "$($_.FullName)"}
после слишком большого поиска я выясняю простой строки без изменение кодирование - это:
Get-Content path/to/file.ext | out-file -encoding ASCII targetFile.ext
немного старый и другой, так как мне нужно было изменить определенную строку во всех экземплярах определенного имени файла.
и Set-Content
не возвращал последовательные результаты, поэтому мне пришлось прибегнуть к Out-File
.
код ниже:
$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
}
Это то, что лучше всего работало для меня в этой версии PowerShell:
майора.Незначительный.Строить.Ревизия
5.1.16299.98
кредит @rominator007
я обернул его в функцию (потому что вы можете использовать его снова)
function Replace-AllStringsInFile($SearchString,$ReplaceString,$FullPathToFile)
{
$content = [System.IO.File]::ReadAllText("$FullPathToFile").Replace("$SearchString","$ReplaceString")
[System.IO.File]::WriteAllText("$FullPathToFile", $content)
}
Примечание:это не чувствительно к регистру!!!!!
посмотреть этот пост: строку.Заменить игнорируя регистр
небольшая коррекция для команды Set-Content. Если искомая строка не найдена Set-Content
команда будет пустой (пустой) целевой файл.
Вы можете сначала проверить, если строка, которую вы ищете или нет. Если нет, это ничего не заменит.
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"}