Как использовать значения (считанные из файла .ps1), чтобы обновить значения другого файла .ps1 - PullRequest
0 голосов
/ 19 мая 2019

У меня есть 4.ps1 файл, который выглядит так

#akabradabra
$one = 'o'

#bibi
$two = 't'

$three = 't'              #ok thr


#four
$four = 'four'

И 3.ps1 файл, который выглядит так

#akabradabra
$one = 'one'

#biblibablibo
$two = 'two'

$three = 'three'              #ok threer

Моя цель - прочитать пару ключ-значение из 4.ps1 и обновить значения в 3.ps1, а если новые пары ключ-значение введены в 4.ps1, просто добавьте их в конец 3.ps1.

Моя идея состоит в том, чтобы использовать строковые функции, такие как .Split('=') и .Replace(' ', ''), чтобы извлечь ключи, и, если ключи совпадают, заменить всю строку в 3.ps1 на строку, найденную в 4.ps1

Я знаю, что использование Get-Variable может помочь, а также будет намного проще работать с данными, если я преобразую все пары ключ-значение в файл .xml или .json, но может кто угодно пожалуйста, покажи мне, как я могу заставить его работать по-своему глупо?

Вот мой код для этого

# Ignore this function, this is used to skip certain key-value pairs
#----------------------------------------------------------------------------
Function NoChange($something) {

    switch ($something) {

        '$CurrentPath' {return $true}
        '$pathToAdmin' {return $true}
        '$hostsPathTocompare' {return $true}
        '$logs' {return $true}
        '$LogFile' {return $true}
        default {return $false}

    }
}
#----------------------------------------------------------------------------

$ReadFromVARS = Get-Content $PSScriptRoot\4.ps1
$WriteToVARS = Get-Content $PSScriptRoot\3.ps1

foreach ($oldVar in $ReadFromVARS) {

    if (('' -eq $oldVar) -or ($oldVar -match '\s*#+\w*')) {
        continue
    } elseif ((NoChange ($oldVar.Split('=').Replace(' ', '')[0]))) {
        continue
    } else {
        $var = 0
        #$flag = $false
        while ($var -ne $WriteToVARS.Length) {
            if ($WriteToVARS[$var] -eq '') {
                $var += 1
                continue
            } elseif ($WriteToVARS[$var] -match '\s*#+\w*') {
                $var += 1
                continue
            } elseif ($oldVar.Split('=').Replace(' ', '')[0] -eq $WriteToVARS[$var].Split('=').Replace(' ', '')[0]<# -and !$flag#>) {
                $oldVar
                $WriteToVARS.replace($WriteToVARS[$var], $oldVar) | Set-Content -Path $PSScriptRoot\3.ps1 -Force
                break
                #$var += 1
                #$flag = $true
            } elseif (<#!$flag -and #>($var -eq $WriteToVARS.Length)) {
                Add-Content -Path $PSScriptRoot\3.ps1 -Value $oldVar -Force
                $var += 1
            } else {
                $var += 1
            }
        }
    }
}

Я не столкнулся с какими-либо ошибками, но он обновил только одну пару ключ-значение ($two = t) и не добавил новые пары ключ-значение в конце. Вот результат, который я получил

#akabradabra
$one = 'one'

#biblibablibo
$two = 't'

$three = 'three'              #ok threer

Ответы [ 2 ]

1 голос
/ 19 мая 2019

Если я правильно понимаю ваш вопрос, я думаю, Dot-Sourcing - это то, что вам нужно.

Оператор точечного источника PowerShell переносит файлы скриптов в текущий сеансобъем.Это способ повторно использовать скрипт.Все функции сценария и переменные, определенные в файле сценария, становятся частью сценария, в который он входит из точек.Это похоже на копирование и вставку текста из файла сценария непосредственно в сценарий.

Чтобы сделать его видимым, используйте Dot-Sourcing для считывания переменных из файла 3.ps1, отображения переменных и ихценности.Следующий точечный исходный файл 4.ps1 и снова отобразите переменные:

. 'D:\3.ps1'

Write-Host "Values taken from file 3.ps1" -ForegroundColor Yellow

"`$one   : $one"
"`$two   : $two"
"`$three : $three"
"`$four  : $four"   # does not exist yet

. 'D:\4.ps1'

Write-Host "Values after dot-sourcing file 4.ps1" -ForegroundColor Yellow

"`$one   : $one"
"`$two   : $two"
"`$three : $three"
"`$four  : $four"

Результат будет

Values taken from file 3.ps1
$one   : one
$two   : two
$three : three
$four  : 
Values after dot-sourcing file 4.ps1
$one   : o
$two   : t
$three : t
$four  : four

Если вы хотите записать эти переменные обратнофайл сценария ps1, который вы можете:

'one','two','three','four' | Get-Variable | ForEach-Object { 
    '${0} = "{1}"' -f $_.Name,$_.Value
} | Set-Content 'D:\5.ps1' -Force
0 голосов
/ 21 мая 2019

Ответ Тео предоставляет более простой способ сделать то же самое

Кроме того, преобразование ваших файлов конфигурации в JSON или XML также значительно облегчит работу

Моя первоначальная идея заключалась в том, чтобы прочитать и 4.ps1, и 3.ps1 (это мои файлы конфигурации, я храню только переменные внутри и переключаю оператор, чтобы помочь выбрать правильные переменные), а затем перезаписать 3.ps1 всемиразница обнаружена, но я не смог заставить ее работать, поэтому я создал новый 5.ps1 и просто написал все, что мне нужно 5.ps1.

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

Для меня было препятствием то, что у меня было switch заявлений и определенных $variables, которые я хотелигнорировать (в моем реальном проекте), поэтому я использовал Regex , чтобы избежать этого.

$ReadFromVARS = Get-Content $PSScriptRoot\4.ps1
$WriteToVARS = Get-Content $PSScriptRoot\3.ps1
New-Item -ItemType File -Path $PSScriptRoot\5.ps1 -Force

Function NoChange($something) {

    switch ($something) {

        '$CurrentPath' {return $true}
        '$pathToAdmin' {return $true}
        '$hostsPathTocompare' {return $true}
        '$logs' {return $true}
        '$LogFile' {return $true}
        default {return $false}

    }
}

$listOfOldVars = @()
$switchStatementStart = "^switch(\s)*\(\`$(\w)+\)(\s)*(\n)*\{"
$switchStatementContent = "(\s)*(\n)*(\t)*\'\w+(\.\w+)+\'(\s)*\{(\s)*\`$\w+(\s)*=(\s)*\@\((\s)*\'\w+(\.\w+)+\'(\s)*(,(\s)*\'\w+(\.\w+)+\'(\s)*)*\)\}"
$switchStatementDefault = "(\s)*(\n)*(\t)*Default(\s)*\{\`$\w+(\s)*=(\s)*\@\((\s)*\'\w+(\.\w+)+\'(\s)*(,(\s)*\'\w+(\.\w+)+\'(\s)*)*\)\}\}"
$switchStatementEnd = "(\s)*(\n)*(\t)*\}"


foreach ($oldVar in $ReadFromVARS) {

    if (('' -eq $oldVar) -or ($oldVar -match '^#+\w*')) {
        continue
    } elseif ((NoChange $oldVar.Split('=').Replace(' ', '')[0])) {
        continue
    } else {
        $var = 0
        while ($var -ne $WriteToVARS.Length) {
            if ($WriteToVARS[$var] -eq '') {
                $var += 1
                continue
            } elseif ($WriteToVARS[$var] -match '^#+\w*') {
                $var += 1
                continue
            } elseif ($oldVar -match $switchStatementStart -or $oldVar -match $switchStatementContent -or $oldVar -match $switchStatementDefault -or $oldVar -match $switchStatementEnd) {
                Add-Content -Path "$PSScriptRoot\5.ps1" -Value $oldVar -Force
                $listOfOldVars += ($oldVar)
                break
            } elseif ($oldVar.Split('=').Replace(' ', '')[0] -eq $WriteToVARS[$var].Split('=').Replace(' ', '')[0]) {
                Add-Content -Path "$PSScriptRoot\5.ps1" -Value $oldVar -Force
                $listOfOldVars += ($oldVar.Remove(0,1).Split('=').Replace(' ', '')[0])
                break
            } else {
                $var += 1
            }
        }
    }
}

foreach ($newVar in $WriteToVARS) {
    if ($newVar.StartsWith('#') -or $newVar -eq '') {
        continue
    } elseif ($newVar -match $switchStatementStart -or $newVar -match $switchStatementContent -or $newVar -match $switchStatementDefault -or $newVar -match $switchStatementEnd) {

    } elseif (($newVar.Remove(0,1).Split('=').Replace(' ', '')[0]) -in $listOfOldVars) {
        continue
    } else {
        Add-Content -Path "$PSScriptRoot\5.ps1" -Value $newVar -Force
    }
}
...