如何使用PowerShell替换文件中的多个字符串

Ivo*_*cky 96 powershell replace

我正在编写一个用于自定义配置文件的脚本.我想在这个文件中替换多个字符串实例,我尝试使用PowerShell来完成这项工作.

它适用于单个替换,但执行多次替换非常慢,因为每次它必须再次解析整个文件,并且此文件非常大.该脚本如下所示:

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'
(Get-Content $original_file) | Foreach-Object {
    $_ -replace 'something1', 'something1new'
    } | Set-Content $destination_file
Run Code Online (Sandbox Code Playgroud)

我想要这样的东西,但我不知道如何写它:

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'
(Get-Content $original_file) | Foreach-Object {
    $_ -replace 'something1', 'something1aa'
    $_ -replace 'something2', 'something2bb'
    $_ -replace 'something3', 'something3cc'
    $_ -replace 'something4', 'something4dd'
    $_ -replace 'something5', 'something5dsf'
    $_ -replace 'something6', 'something6dfsfds'
    } | Set-Content $destination_file
Run Code Online (Sandbox Code Playgroud)

dah*_*byk 151

一种选择是将-replace操作链接在一起.在`每一行的末尾逸出换行符,引起PowerShell来继续解析下一行的表达:

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'
(Get-Content $original_file) | Foreach-Object {
    $_ -replace 'something1', 'something1aa' `
       -replace 'something2', 'something2bb' `
       -replace 'something3', 'something3cc' `
       -replace 'something4', 'something4dd' `
       -replace 'something5', 'something5dsf' `
       -replace 'something6', 'something6dfsfds'
    } | Set-Content $destination_file
Run Code Online (Sandbox Code Playgroud)

另一种选择是分配一个中间变量:

$x = $_ -replace 'something1', 'something1aa'
$x = $x -replace 'something2', 'something2bb'
...
$x
Run Code Online (Sandbox Code Playgroud)

  • 是的,PowerShell 就是这样……毫无帮助。您必须自己检测编码,例如 https://github.com/dahlbyk/posh-git/blob/869d4c5159797755bc04749db47b166136e59132/install.ps1#L23-L37 (3认同)

小智 23

要获得George Howarth使用多个替换项正常工作的帖子,您需要删除中断,将输出分配给变量($ line),然后输出变量:

$lookupTable = @{
    'something1' = 'something1aa'
    'something2' = 'something2bb'
    'something3' = 'something3cc'
    'something4' = 'something4dd'
    'something5' = 'something5dsf'
    'something6' = 'something6dfsfds'
}

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'

Get-Content -Path $original_file | ForEach-Object {
    $line = $_

    $lookupTable.GetEnumerator() | ForEach-Object {
        if ($line -match $_.Key)
        {
            $line = $line -replace $_.Key, $_.Value
        }
    }
   $line
} | Set-Content -Path $destination_file
Run Code Online (Sandbox Code Playgroud)

  • 这是迄今为止我见过的最好的方法。唯一的问题是我必须首先将整个文件内容读取到变量中才能使用相同的源/目标文件路径。 (2认同)

Ian*_*son 11

使用PowerShell版本3,您可以将替换调用链接在一起:

 (Get-Content $sourceFile) | ForEach-Object {
    $_.replace('something1', 'something1').replace('somethingElse1', 'somethingElse2')
 } | Set-Content $destinationFile
Run Code Online (Sandbox Code Playgroud)


Geo*_*rth 8

假设每行只能有一个'something1''something2'等,您可以使用查找表:

$lookupTable = @{
    'something1' = 'something1aa'
    'something2' = 'something2bb'
    'something3' = 'something3cc'
    'something4' = 'something4dd'
    'something5' = 'something5dsf'
    'something6' = 'something6dfsfds'
}

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'

Get-Content -Path $original_file | ForEach-Object {
    $line = $_

    $lookupTable.GetEnumerator() | ForEach-Object {
        if ($line -match $_.Key)
        {
            $line -replace $_.Key, $_.Value
            break
        }
    }
} | Set-Content -Path $destination_file
Run Code Online (Sandbox Code Playgroud)

如果你能拥有这些的不止一个,只是删除breakif声明.


小智 7

第三种选择,对于流水线单行程,是嵌套-replaces:

PS> ("ABC" -replace "B","C") -replace "C","D"
ADD
Run Code Online (Sandbox Code Playgroud)

和:

PS> ("ABC" -replace "C","D") -replace "B","C"
ACD
Run Code Online (Sandbox Code Playgroud)

这样可以保留执行顺序,易于阅读,并且非常适合管道.我更喜欢使用括号进行显式控制,自我记录等.没有它们可以工作,但你相信这有多远?

-Replace是一个比较运算符,它接受一个对象并返回一个推测修改过的对象.这就是您可以如上所示堆叠或嵌套它们的原因.

请参阅:

help about_operators
Run Code Online (Sandbox Code Playgroud)