我有一个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
中的整行替换为{{ 1}}
我知道使用4.ps1
可以解决问题,而且如果我将所有键值对都转换为Get-Variable
或{{1 }}文件,但任何人都可以告诉我如何以自己的愚蠢方式使其工作吗?
这是我的代码
.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
}
}
}
}
答案 0 :(得分:1)
如果我正确理解了您的问题,我认为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
答案 1 :(得分:0)
Theo的答案提供了一种更简单的方法来完成相同的事情
此外,将您的Config文件转换为JSON或XML也将使这项工作更加容易
我的最初想法是同时读取4.ps1
和3.ps1
(这些是我的配置文件,我只在其中存储变量并使用switch语句来帮助选择正确的变量)然后覆盖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
}
}