Powershell 新手:如何使用嵌套的 foreach 或数组(或任何其他解决方案)将 2 个或更多变量放入同一文件?
Novice at Powershell: How do I get 2 or more variables into the same file using either nested foreach or arrays (or any other solution)?
我创建了一个 powershell gui 来创建 IAAS cloudformation 模板。我 运行 关注的问题是:
该模板成功地为所有环境创建了文件夹结构,一旦它这样做,它就会开始为部署创建每个文件的过程。
每个文件名来自变量:
$is = $textbox10.Lines (TEXTBOX WITH A SERVER NAME LIST)
如果我输入 3 个服务器名称,它将在所有文件夹中使用 $i 中的名称(这部分有效)创建 3 个文件
###################################################################
### COPY AND RENAME PARAMETER FILES IN INFRASTRUCTURE FOLDER ###
###################################################################
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\dev\params_ans_DVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\sit\params_ans_SVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\uat\params_ans_UVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\prep\params_ans_PVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\prod\params_ans_XVW$i.yml"
完成后,它应该尝试遍历它创建的每个文件并添加其他变量。在这个 case/example 中:$a 变量
$azs = $textbox1.Lines
下面是我当前所在位置的示例。
$is = "TEST01","TEST02","TEST03"
#Write-Host $is
$azs = "a","b","c"
#Write-Host $azs
foreach ($i in $is)
{
###################################################################
### COPY AND RENAME PARAMETER FILES IN INFRASTRUCTURE FOLDER ###
###################################################################
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\dev\params_ans_DVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\sit\params_ans_SVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\uat\params_ans_UVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\prep\params_ans_PVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\prod\params_ans_XVW$i.yml"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\sit\params_SVW$i.json"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\uat\params_UVW$i.json"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\prep\params_PVW$i.json"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\prod\params_XVW$i.json"
#############################################
### REPLACE CONTENT IN PARAMETER FILES ###
###########################################
foreach ($a in $azs)
{
#Write-Host $a
## REPLACE AVAILABILITY ZONES IN TEMPLATE ##
(Get-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
(Get-Content "$($infrawindowsbasefolder)\sit\params_SVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\sit\params_SVW$i.json"
(Get-Content "$($infrawindowsbasefolder)\uat\params_UVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-$($a)" } | Set-Content "$($infrawindowsbasefolder)\uat\params_UVW$i.json"
(Get-Content "$($infrawindowsbasefolder)\prep\params_PVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\prep\params_PVW$i.json"
(Get-Content "$($infrawindowsbasefolder)\prod\params_XVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\prod\params_XVW$i.json"
}
}
运行时,为每个环境创建的 3 个文件都有第一个变量 $a "a",而不是 "test01-a"、"test02-b"、"test03-c"。
问题是您的要替换文本的搜索模式在循环的第一遍中被替换,并且在后两个循环中不再存在。让我们简化一下,只在一个文件上循环:
foreach ($a in $azs)
{
#Write-Host $a
## REPLACE AVAILABILITY ZONES IN TEMPLATE ##
(Get-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
}
假设文件 params_DVWTEST01.json
包含文本:
<region>
availability-zone
<region>
现在你的循环第一次运行,$a = 'a'
。在循环中,您获取文件的内容,执行字符串替换,然后使用 Set-Content
保存更新后的文件。最终产品,该文件现在包含:
<region>
us-east-1a
<region>
第二个循环开始,这次 $a = 'b'
。在你的循环中你得到了文件的内容,它试图执行字符串替换,但是 'availability-zone' 在要替换的文件中没有任何地方,所以它按原样保存文件。
第三个循环,其中 $a = 'c'
的执行与第二个循环完全相同。它加载文件,找不到要替换的内容,然后按原样保存文件。如果您希望它包含 $azs
中的所有三个项目,您需要将字符串组合成一个字符串,并将其用作替换。
$AllZones = ($azs|ForEach{"us-east-1$_"}) -join ", "
现在$AllZones = "us-east-1a, us-east-1b, us-east-1c"
。然后将其用作替换字符串,不需要内部循环。
$AllZones = ($azs|ForEach{"us-east-1$_"}) -join ", "
## REPLACE AVAILABILITY ZONES IN TEMPLATE ##
(Get-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json") | foreach-object { $_ -replace "availability-zone", $AllZones } | Set-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
编辑: 看起来你想在服务器之间循环,这样每个服务器都有不同的位置,或者至少让服务器分布在不同的位置位置。有几种方法可以做到这一点。最简单的是,如果您拥有与地点数量相同的服务器。在这种情况下,您切换到使用 For()
循环而不是 ForEach()
循环。然后事情开始看起来像这样:
$is = "TEST01","TEST02","TEST03"
#Write-Host $is
$azs = "a","b","c"
#Write-Host $azs
for ($y=0; $y -lt $is.count; $y++)
{
$i = $is[$y]
然后当您稍后进行替换时,您会引用 $azs[$y]
,例如:
(Get-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($azs[$y])" } | Set-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
然后 TEST01 得到 "us-east-1a",TEST02 得到 "us-east-1b",TEST03 得到 "us-east-1c"。如果您的服务器数量和位置数量相等,则非常简单。
让我们看看另一种方法,您可能有不同数量的服务器和位置,并且您希望将服务器分布在有限数量的位置。这将是类似的情况,但我们必须做一些数学运算才能循环遍历位置列表。让我们从设置更多服务器开始,我们将扩展到 5 个。
$is = "TEST01","TEST02","TEST03","TEST04","TEST05"
我们将保持区域不变,a、b 和 c。现在为了简单起见,我们将只输出我们分配给每个服务器的区域到屏幕:
For($y=0; $y -lt $is.count; $y++){
"Assigning server '$($is[$y])' to region 'us-east-1$($azs[$y%$azs.count])'"
}
输出结果为:
Assigning server 'TEST01' to region 'us-east-1a'
Assigning server 'TEST02' to region 'us-east-1b'
Assigning server 'TEST03' to region 'us-east-1c'
Assigning server 'TEST04' to region 'us-east-1a'
Assigning server 'TEST05' to region 'us-east-1b'
其中的魔力是 $y%$azs.count
。这样做是将 $y
的当前迭代除以 $azs.count
(即 3)后的余数。所以第一次通过循环它是 0 除以 3,即 0 余数为 0。$azs[0] = 'a'
。下一次迭代是1除以3,即0余1。$azs[1] = 'b'
。迭代 3 非常相似,产生 'c'。迭代 4 更有趣,它是 3 除以 3,即 1 余数为 0,这就是导致我们循环回到 $azs[0] = 'a'
.
开头的原因
我创建了一个 powershell gui 来创建 IAAS cloudformation 模板。我 运行 关注的问题是:
该模板成功地为所有环境创建了文件夹结构,一旦它这样做,它就会开始为部署创建每个文件的过程。
每个文件名来自变量:
$is = $textbox10.Lines (TEXTBOX WITH A SERVER NAME LIST)
如果我输入 3 个服务器名称,它将在所有文件夹中使用 $i 中的名称(这部分有效)创建 3 个文件
###################################################################
### COPY AND RENAME PARAMETER FILES IN INFRASTRUCTURE FOLDER ###
###################################################################
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\dev\params_ans_DVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\sit\params_ans_SVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\uat\params_ans_UVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\prep\params_ans_PVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\prod\params_ans_XVW$i.yml"
完成后,它应该尝试遍历它创建的每个文件并添加其他变量。在这个 case/example 中:$a 变量
$azs = $textbox1.Lines
下面是我当前所在位置的示例。
$is = "TEST01","TEST02","TEST03"
#Write-Host $is
$azs = "a","b","c"
#Write-Host $azs
foreach ($i in $is)
{
###################################################################
### COPY AND RENAME PARAMETER FILES IN INFRASTRUCTURE FOLDER ###
###################################################################
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\dev\params_ans_DVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\sit\params_ans_SVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\uat\params_ans_UVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\prep\params_ans_PVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\prod\params_ans_XVW$i.yml"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\sit\params_SVW$i.json"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\uat\params_UVW$i.json"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\prep\params_PVW$i.json"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\prod\params_XVW$i.json"
#############################################
### REPLACE CONTENT IN PARAMETER FILES ###
###########################################
foreach ($a in $azs)
{
#Write-Host $a
## REPLACE AVAILABILITY ZONES IN TEMPLATE ##
(Get-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
(Get-Content "$($infrawindowsbasefolder)\sit\params_SVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\sit\params_SVW$i.json"
(Get-Content "$($infrawindowsbasefolder)\uat\params_UVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-$($a)" } | Set-Content "$($infrawindowsbasefolder)\uat\params_UVW$i.json"
(Get-Content "$($infrawindowsbasefolder)\prep\params_PVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\prep\params_PVW$i.json"
(Get-Content "$($infrawindowsbasefolder)\prod\params_XVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\prod\params_XVW$i.json"
}
}
运行时,为每个环境创建的 3 个文件都有第一个变量 $a "a",而不是 "test01-a"、"test02-b"、"test03-c"。
问题是您的要替换文本的搜索模式在循环的第一遍中被替换,并且在后两个循环中不再存在。让我们简化一下,只在一个文件上循环:
foreach ($a in $azs)
{
#Write-Host $a
## REPLACE AVAILABILITY ZONES IN TEMPLATE ##
(Get-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
}
假设文件 params_DVWTEST01.json
包含文本:
<region>
availability-zone
<region>
现在你的循环第一次运行,$a = 'a'
。在循环中,您获取文件的内容,执行字符串替换,然后使用 Set-Content
保存更新后的文件。最终产品,该文件现在包含:
<region>
us-east-1a
<region>
第二个循环开始,这次 $a = 'b'
。在你的循环中你得到了文件的内容,它试图执行字符串替换,但是 'availability-zone' 在要替换的文件中没有任何地方,所以它按原样保存文件。
第三个循环,其中 $a = 'c'
的执行与第二个循环完全相同。它加载文件,找不到要替换的内容,然后按原样保存文件。如果您希望它包含 $azs
中的所有三个项目,您需要将字符串组合成一个字符串,并将其用作替换。
$AllZones = ($azs|ForEach{"us-east-1$_"}) -join ", "
现在$AllZones = "us-east-1a, us-east-1b, us-east-1c"
。然后将其用作替换字符串,不需要内部循环。
$AllZones = ($azs|ForEach{"us-east-1$_"}) -join ", "
## REPLACE AVAILABILITY ZONES IN TEMPLATE ##
(Get-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json") | foreach-object { $_ -replace "availability-zone", $AllZones } | Set-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
编辑: 看起来你想在服务器之间循环,这样每个服务器都有不同的位置,或者至少让服务器分布在不同的位置位置。有几种方法可以做到这一点。最简单的是,如果您拥有与地点数量相同的服务器。在这种情况下,您切换到使用 For()
循环而不是 ForEach()
循环。然后事情开始看起来像这样:
$is = "TEST01","TEST02","TEST03"
#Write-Host $is
$azs = "a","b","c"
#Write-Host $azs
for ($y=0; $y -lt $is.count; $y++)
{
$i = $is[$y]
然后当您稍后进行替换时,您会引用 $azs[$y]
,例如:
(Get-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($azs[$y])" } | Set-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
然后 TEST01 得到 "us-east-1a",TEST02 得到 "us-east-1b",TEST03 得到 "us-east-1c"。如果您的服务器数量和位置数量相等,则非常简单。
让我们看看另一种方法,您可能有不同数量的服务器和位置,并且您希望将服务器分布在有限数量的位置。这将是类似的情况,但我们必须做一些数学运算才能循环遍历位置列表。让我们从设置更多服务器开始,我们将扩展到 5 个。
$is = "TEST01","TEST02","TEST03","TEST04","TEST05"
我们将保持区域不变,a、b 和 c。现在为了简单起见,我们将只输出我们分配给每个服务器的区域到屏幕:
For($y=0; $y -lt $is.count; $y++){
"Assigning server '$($is[$y])' to region 'us-east-1$($azs[$y%$azs.count])'"
}
输出结果为:
Assigning server 'TEST01' to region 'us-east-1a'
Assigning server 'TEST02' to region 'us-east-1b'
Assigning server 'TEST03' to region 'us-east-1c'
Assigning server 'TEST04' to region 'us-east-1a'
Assigning server 'TEST05' to region 'us-east-1b'
其中的魔力是 $y%$azs.count
。这样做是将 $y
的当前迭代除以 $azs.count
(即 3)后的余数。所以第一次通过循环它是 0 除以 3,即 0 余数为 0。$azs[0] = 'a'
。下一次迭代是1除以3,即0余1。$azs[1] = 'b'
。迭代 3 非常相似,产生 'c'。迭代 4 更有趣,它是 3 除以 3,即 1 余数为 0,这就是导致我们循环回到 $azs[0] = 'a'
.