简体   繁体   English

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

[英]How to replace multiple strings in a file using PowerShell

I am writing a script for customising a configuration file. 我正在编写用于自定义配置文件的脚本。 I want to replace multiple instances of strings within this file, and I tried using PowerShell to do the job. 我想替换此文件中字符串的多个实例,并且尝试使用PowerShell来完成这项工作。

It works fine for a single replace, but doing multiple replaces is very slow because each time it has to parse the whole file again, and this file is very large. 对于单个替换它可以很好地工作,但是进行多次替换非常慢,因为每次必须重新解析整个文件时,此文件非常大。 The script looks like this: 该脚本如下所示:

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

I want something like this, but I don't know how to write it: 我想要这样的东西,但是我不知道该怎么写:

$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

One option is to chain the -replace operations together. 一种选择是将-replace操作链接在一起。 The ` at the end of each line escapes the newline, causing PowerShell to continue parsing the expression on the next line: 每行末尾的`转义换行符,从而使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

Another option would be to assign an intermediate variable: 另一种选择是分配一个中间变量:

$x = $_ -replace 'something1', 'something1aa'
$x = $x -replace 'something2', 'something2bb'
...
$x

To get the post by George Howarth working properly with more than one replacement you need to remove the break, assign the output to a variable ($line) and then output the variable: 为了使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

With version 3 of PowerShell you can chain the replace calls together: 使用PowerShell的版本3,可以将replace调用链接在一起:

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

Assuming you can only have one 'something1' or 'something2' , etc. per line, you can use a lookup table: 假设每行只能有一个'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

If you can have more than one of those, just remove the break in the if statement. 如果可以有多个,只需删除if语句中的break

A third option, for a pipelined one-liner is to nest the -replaces: 对于流水线一线式的第三个选择是嵌套-replaces:

PS> ("ABC" -replace "B","C") -replace "C","D"
ADD

And: 和:

PS> ("ABC" -replace "C","D") -replace "B","C"
ACD

This preserves execution order, is easy to read, and fits neatly into a pipeline. 这样可以保留执行顺序,易于阅读,并且可以整齐地放入管道中。 I prefer to use parentheses for explicit control, self-documentation, etc. It works without them, but how far do you trust that? 我更喜欢将括号用于显式控制,自我说明等。如果没有括号,它就可以工作,但是您对此有多信任?

-Replace is a Comparison Operator, which accepts an object and returns a presumably modified object. -Replace是一个比较运算符,它接受一个对象并返回一个可能被修改的对象。 This is why you can stack or nest them as shown above. 这就是为什么您可以如上所示堆叠或嵌套它们的原因。

Please see: 请参见:

help about_operators

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM