Функция для замены текста в файле и его сохранения - PullRequest
1 голос
/ 16 июня 2020

Я новичок в программировании, я пытаюсь улучшить следующий код сценария, я думал о создании функции, чтобы улучшить его, но я не знаю, с чего начать, и это лучший вариант. 1002 *

Ответы [ 3 ]

1 голос
/ 16 июня 2020

Во-первых, я бы, наверное, попробовал прочитать файл только один раз. Затем, поскольку вы выполняете много подобных операций, я бы поместил все данные об операциях в массив, а затем перебрал бы эти данные.

В этом коде я сначала прочитал файл. Затем я определяю все строки, которые должны быть заменены, вместе со строками, которые должны их заменить. Затем я использую al oop для перебора данных, чтобы мы не повторяли один и тот же код все время.

$data = Get-Content -Path $copyFileLocation -Raw

$replacements = @(
    @('"INSTANCENAME="TEST""', $NUEVAINESTANCIA),
    @('"INSTANCEID="TEST""', $NUEVAINESTANCIAID),
    @("NT Service\SQLAgent#TEST", $CUENTAAGTN),
    @("NT Service\MSSQL#TEST", $CUENTASQLSER),
    @("##MyUser##", "$env:UserDomain\$env:USERNAME")
)

$replacements | ForEach-Object {
    $data = $data.Replace($_[0], $_[1])
}

Set-Content -Path $copyFileLocation -Value $data

Также можно сделать это еще короче, если вы используете конвейер вместо присвоение данных переменной

$data = Get-Content -Path $copyFileLocation -Raw

@(
    @('"INSTANCENAME="TEST""', $NUEVAINESTANCIA),
    @('"INSTANCEID="TEST""', $NUEVAINESTANCIAID),
    @("NT Service\SQLAgent#TEST", $CUENTAAGTN),
    @("NT Service\MSSQL#TEST", $CUENTASQLSER),
    @("##MyUser##", "$env:UserDomain\$env:USERNAME")
) | ForEach-Object {
    $data = $data.Replace($_[0], $_[1])
}

Set-Content -Path $copyFileLocation -Value $data

Изменить: пропустил, что вы спрашивали, как превратить его в функцию.

Глядя на то, что вы делаете, я предполагаю, что вы изменяете SQL файл автоматической установки и присвоил ему соответствующее имя.

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

Function Set-SQLInstallFileVariables {
    Param(
        [Parameter(Mandatory)][string]$FilePath,
        [Parameter(Mandatory)][string]$NUEVAINESTANCIA,
        [Parameter(Mandatory)][string]$NUEVAINESTANCIAID,
        [Parameter(Mandatory)][string]$CUENTAAGTN,
        [Parameter(Mandatory)][string]$CUENTASQLSER,
        [string]$MyUser = "$env:UserDomain\$env:USERNAME"
    )

    $data = Get-Content -Path $FilePath -Raw

    @(
        @('"INSTANCENAME="TEST""', $NUEVAINESTANCIA),
        @('"INSTANCEID="TEST""', $NUEVAINESTANCIAID),
        @("NT Service\SQLAgent#TEST", $CUENTAAGTN),
        @("NT Service\MSSQL#TEST", $CUENTASQLSER),
        @("##MyUser##", $MyUser)
    ) | ForEach-Object {
        $data = $data.Replace($_[0], $_[1])
    }

    Set-Content -Path $copyFileLocation -Value $data
}
0 голосов
/ 16 июня 2020

Вот моя попытка. Это не значит быть худым. Скорее, чтобы быть действительно ясным в отношении того, что он делает, будучи наполненным функциями (слишком много) и не позволяя вам получать контент несколько раз. Надеюсь, мой текст читабелен и даст вам лучшее представление об использовании конвейера и функций :)

    Function Replace1 {Process{$_ -replace '"INSTANCENAME="TEST""',$NUEVAINESTANCIA}}
    Function Replace2 {Process{$_ -replace '"INSTANCEID="TEST""',$NUEVAINESTANCIAID}}
    Function Replace3 {Process{$_ -replace "NT Service\SQLAgent#TEST", $CUENTAAGTN}}
    Function Replace4 {Process{$_ -replace "NT Service\MSSQL#TEST", $CUENTASQLSER}}
    Function Replace6 {Process{$_ -replace "##MyUser##", $user}}

    $user = "$env:UserDomain\$env:USERNAME"

    Write-Host $user

    Get-Content -path $copyFileLocation | Replace1 | Replace2 | Replace3 | Replace4 | Replace5 | Replace6 | Set-Content -path $copyFileLocation
0 голосов
/ 16 июня 2020

Первое, на что следует обратить внимание, это то, что вы читаете и записываете файл снова и снова при каждой замене, что не очень эффективно. Это не нужно; после прочтения содержимое находится в строковой переменной и может обрабатываться в памяти несколько раз перед записью обратно в файл.

Один из подходов - использовать строковые массивы , которые содержат строки поиска и замены. Чтобы это работало должным образом, оба массива должны иметь одинаковое количество элементов.

$inputFile  = 'D:\Test\TheFile.txt'          # your input file path here ($copyFileLocation)
$outputFile = 'D:\Test\TheReplacedFile.txt'  # for safety create a new file instead of overwriting the original

$searchStrings  = '"INSTANCENAME="TEST""','"INSTANCEID="TEST""',"NT Service\SQLAgent#TEST","NT Service\MSSQL#TEST","##MyUser##"
$replaceStrings = $NUEVAINESTANCIA, $NUEVAINESTANCIAID, $CUENTAAGTN, $CUENTASQLSER, "$env:UserDomain\$env:USERNAME"

# get the current content of the file
$content = Get-Content -path $copyFileLocation -Raw

# loop over the search and replace strings to do all replacements
for ($i = 0; $i -lt $searchStrings.Count; $i++) {
    $content = $content -replace [regex]::Escape($searchStrings[$i]), $replaceString[$i]
}

# finally, write the updated content to a (new) file
$content | Set-Content -Path $copyFileLocation

Другой подход - использовать Hashtable, в котором хранятся как строки поиска, так и строки замены:

$inputFile  = 'D:\Test\TheFile.txt'          # your input file path here ($copyFileLocation)
$outputFile = 'D:\Test\TheReplacedFile.txt'  # for safety create a new file instead of overwriting the original

$hash = @{
    '"INSTANCENAME="TEST""'    = $NUEVAINESTANCIA
    '"INSTANCEID="TEST""'      = $NUEVAINESTANCIAID
    "NT Service\SQLAgent#TEST" = $CUENTAAGTN
    "NT Service\MSSQL#TEST"    = $CUENTASQLSER
    "##MyUser##"               = "$env:UserDomain\$env:USERNAME"
}

# get the current content of the file
$content = Get-Content -path $copyFileLocation -Raw

# loop over the items in the hashtable to do all replacements
$hash.GetEnumerator() | ForEach-Object {
    # the `$_` is an automatic variable you get within a ForEach-Object{}
    # It represents a single item on each iteration.
    $content = $content -replace [regex]::Escape($_.Key), $_.Value
}

# finally, write the updated content to a (new) file
$content | Set-Content -Path $copyFileLocation

В обоих случаях мы используем -replace, заменяющее регулярное выражение без учета регистра. Поскольку ваши строки поиска содержат символы, которые имеют особое значение в регулярном выражении (# и \), нам нужно экранировать их с помощью [regex]::Escape()

Надеюсь, что это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...