首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Powershell新手:如何使用嵌套的foreach或数组(或任何其他解决方案)将2个或多个变量放入同一个文件?

Powershell新手:如何使用嵌套的foreach或数组(或任何其他解决方案)将2个或多个变量放入同一个文件?
EN

Stack Overflow用户
提问于 2020-02-04 22:05:41
回答 1查看 133关注 0票数 0

我创建了一个powershell gui来创建IAAS cloudformation模板。我遇到的问题是:

模板成功地为所有环境创建文件夹结构,一旦它开始为部署创建每个文件的过程。

每个文件名都来自变量:

代码语言:javascript
复制
$is = $textbox10.Lines  (TEXTBOX WITH A SERVER NAME LIST)

如果我输入3个服务器名称,它将在所有文件夹中使用$i中的名称创建3个文件(此部分有效)

代码语言:javascript
复制
###################################################################
###   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"

一旦完成该操作,它应该尝试遍历它创建的每个文件并添加其他变量。在本例/示例中:$a变量

代码语言:javascript
复制
$azs = $textbox1.Lines

下面是我目前所在地点的一个例子。

代码语言:javascript
复制
        $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“。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-04 22:55:42

问题是要替换的文本搜索模式在循环的第一次遍历中被替换,而在第二个循环中不再存在。让我们简化一下,只在一个文件上循环:

代码语言:javascript
复制
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包含文本:

代码语言:javascript
复制
<region>
    availability-zone
<region>

现在,您的循环第一次运行,其中$a = 'a'。在循环中获取文件的内容,执行字符串替换,并使用Set-Content保存更新的文件。最终产品,该文件现在包含:

代码语言:javascript
复制
<region>
    us-east-1a
<region>

第二个循环开始,这次是$a = 'b'。在您的循环中,您可以获得文件的内容,它尝试执行字符串替换,但是文件中的“可用性区域”没有被替换的地方,所以它保存文件就像现在一样。

第三个循环,其中$a = 'c'的执行与第二个循环完全一样。它加载文件,找不出要替换的东西,并按原样保存文件。如果您希望它包含$azs中的所有三个项,则需要将字符串组合成单个字符串,并将其用作您的替代项。

代码语言:javascript
复制
$AllZones = ($azs|ForEach{"us-east-1$_"}) -join ", "

现在是$AllZones = "us-east-1a, us-east-1b, us-east-1c"。然后将其用作替换字符串,不需要内部循环。

代码语言:javascript
复制
$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()循环。然后事情开始变成这样:

代码语言:javascript
复制
    $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],例如:

代码语言:javascript
复制
(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。

代码语言:javascript
复制
$is = "TEST01","TEST02","TEST03","TEST04","TEST05"

为了简单起见,我们只需要输出分配给每个服务器到屏幕上的区域:

代码语言:javascript
复制
For($y=0; $y -lt $is.count; $y++){
    "Assigning server '$($is[$y])' to region 'us-east-1$($azs[$y%$azs.count])'"
}

这方面的产出如下:

代码语言:javascript
复制
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'开头的原因。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60066220

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档