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 и т. д.) без необходимости заботиться большую часть времени.
также методы не испортить окончание строки (Unix окончание строки, которые могут быть использованы) в в отличие от алгоритма, использующего Get-Content и piping through to Set-Content.
Так что для меня: меньше вещей, которые могли бы сломаться за эти годы.
малоизвестная вещь при использовании классов .NET заключается в том, что когда вы набрали "[System.IO.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Если вы собираетесь заменить строки в больших текстовых файлах и скорость является проблемой, посмотрите на использование System. IO. StreamReader и System. 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() } }(приведенный выше код не тестировался.)
вероятно, есть более элегантный способ использовать StreamReader и StreamWriter для замены текста в документе, но это должно дать вам хороший отправная точка.
Это сработало для меня, используя текущий рабочий каталог в 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"}
Comments