Подтвердить что ты не робот

Как заменить несколько строк в файле с помощью PowerShell

Я пишу script для настройки файла конфигурации. Я хочу заменить несколько экземпляров строк в этом файле, и я попытался использовать PowerShell для выполнения этой задачи.

Он отлично работает для одной замены, но выполнение нескольких замещений происходит очень медленно, потому что каждый раз, когда ему приходится снова анализировать весь файл, и этот файл очень большой. script выглядит следующим образом:

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

Мне нужно что-то подобное, но я не знаю, как его написать:

$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
4b9b3361

Ответ 1

Один из вариантов заключается в объединении операций -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

Другой вариант - назначить промежуточную переменную:

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

Ответ 2

Чтобы получить сообщение Джорджа Ховарта, работающего правильно с более чем одной заменой, вам нужно удалить разрыв, назначить вывод переменной ($ 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

Ответ 3

Предполагая, что вы можете иметь только один '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

Если вы можете иметь более одного из них, просто удалите break в инструкции if.

Ответ 4

Третий вариант, для конвейерной однострочной линии заключается в том, чтобы вставить -replaces:

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

и

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

Это сохраняет порядок выполнения, легко читается и аккуратно вписывается в конвейер. Я предпочитаю использовать круглые скобки для явного управления, самостоятельной документации и т.д. Он работает без них, но насколько вы этому доверяете?

-Replace - это оператор сравнения, который принимает объект и возвращает предположительно измененный объект. Вот почему вы можете складывать или вставлять их, как показано выше.

Пожалуйста, смотрите:

help about_operators

Ответ 5

С версией 3 PowerShell вы можете объединить вызовы замены:

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