如何用PowerShellreplace文件中的每个string?

使用PowerShell,我想用[MYID]replace给定文件中[MYID]所有确切事件。 最简单的方法是什么?

使用(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)周围的圆括号是必需的:

如果没有括号,内容将被逐行读取,然后沿着stream水线向下stream动,直到达到out-file或set-content,这些内容尝试写入同一个文件,但已经被get-content打开,一个错误。 括号引起内容读取的操作被执行一次(打开,读取和closures)。 只有当所有的行被读取完毕,它们才被一次一个地传送,当它们到达pipe道中的最后一个命令时,它们可以被写入文件。 它与$ content = content相同; $ content | 那里…

我更喜欢使用.NET的File-class及其静态方法,如以下示例所示。

 $content = [System.IO.File]::ReadAllText("c:\bla.txt").Replace("[MYID]","MyValue") [System.IO.File]::WriteAllText("c:\bla.txt", $content) 

与Get-Content一样,这具有使用单个string而不是string数组的优点。 这些方法还可以处理文件的编码(UTF-8 BOM等),而不需要大多数时间。

此外,这些方法不会混淆行结尾(可能使用的Unix行尾),而与使用Get-Content的algorithm相反,并且通过pipe道传递到Set-Content 。

所以对于我来说:这些年来可以打破的东西更less。

使用.NET类的一个鲜为人知的事情是,当你在PowerShell窗口中input“[System.IO.File] ::”时,你可以按下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 

如果您要在大型文本文件中replacestring,并且速度是一个问题,请使用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() } } 

(上面的代码没有经过testing。)

使用StreamReader和StreamWriterreplace文档中的文本可能会有更好的方式,但这应该给您一个很好的起点。

search了太多后,我找出最简单的一行来做这个, 而不改变编码是:

 Get-Content path/to/file.ext | out-file -encoding ASCII targetFile.ext 

这对我使用PowerShell中的当前工作目录。 您需要使用FullName属性,否则将无法在PowerShell版本5中工作。我需要在所有CSPROJ文件中更改目标.NET Framework版本。

 gci -Recurse -Filter *.csproj | % { (get-content "$($_.FullName)") .Replace('<TargetFramework>net47</TargetFramework>', '<TargetFramework>net462</TargetFramework>') | Set-Content "$($_.FullName)"} 

Set-Content命令的小改动。 如果找不到search的string,则Set-Content命令将空白(空)目标文件。

您可以先validation您正在查找的string是否存在。 如果不是,它不会取代任何东西。

 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"}