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'.

开头的原因