使用动态方法替换PowerShell字典中的占位符

时间:2017-03-09 05:23:27

标签: xml powershell dictionary powershell-v2.0

参考Replace placeholders with actual values in PowerShell dictionary 我试图用实际元素值dynamically替换PowerShell字典中的占位符。我从上面的帖子中得到了一个合适的答案,但这并没有多大帮助,因为它是一个静态的解决方案。需求经常变化,所以我不能在PowerShell脚本中硬编码。我对PowerShell脚本进行了一些更改并尝试运行。但是遇到了一些错误。以下是我的代码:

$xmldata = @"
<configuration>
    <environment id="Development">
    <type>Dev</type>
    <client>Arizona%%type%%</client>
    <dataSource>Local%%client%%</dataSource>
    <path>App_Data\%%type%%\%%client%%_%%dataSource%%</path>
    <targetmachines>
        <targetmachine>
        <name>Any</name>
        <remotedirectory>D:\Inetpub\Test</remotedirectory>
        </targetmachine>
    </targetmachines>
    </environment>
</configuration>
"@

[System.Xml.XmlDocument] $configxml = [xml]$xmldata
$environmentId = "Development"
$keyValuePairs = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]"
$configxml.SelectNodes("//configuration/environment[@id='$($environmentId)']//*[not(*)]") | `
    ForEach-Object {
                    if($_.ParentNode.ToString() -ne "targetmachine")
                    {

                        $keyValuePairs.Add($_.Name, $_.InnerText)
                    }
                }

Write-Output $keyValuePairs

Foreach ($key in $keyValuePairs.Keys)
{

    $strings = [regex]::Matches($keyValuePairs[$key], '%%([^/)]+?)%%') |ForEach-Object { $_.Groups[1].Value }
    $strings = $strings | sort -unique

    if ($strings.Count -gt 0)
    {
        $finalValue = $keyValuePairs[$key]
        $finalValue

        foreach ($placeholder in $strings)
        {
            write-host "one of the place holder is" -ForegroundColor Green
            $placeholder
            #replacing all of the placeholders (which exists between %%---%%) with actual values
            $finalValue = $finalValue.Replace("%%$placeholder%%",$keyValuePairs[$placeholder])
        }

        #Replace the original value with actual value
        $keyValuePairs[$key] = $finalValue 
    }
}

Write-Output $keyValuePairs

尝试覆盖字典值时出现以下错误

Collection was modified; enumeration operation may not execute.
At line:33 char:10
+ Foreach ($key in $keyValuePairs.Keys)
+          ~~~~
    + CategoryInfo          : OperationStopped: (:) [], InvalidOperationExcept 
   ion
    + FullyQualifiedErrorId : System.InvalidOperationException

注意:基本上我尝试使用动态方法替换字典值中的占位符。有人可以帮助我如何实现以下输出

Key                        Value
---                        -----
type                       Dev
client                     ArizonaDev
dataSource                 LocalArizonaDev
path                       App_Data\Dev\ArizonaDev_LocalArizonaDev

2 个答案:

答案 0 :(得分:0)

对于给定的xml数据集,以下脚本应按预期工作。对于更复杂的嵌套占位符结构,请参阅### loop while ...条评论(并考虑一下)。

$xmldata = @"
<configuration>
    <environment id="Development">
    <type>Dev</type>
    <client>Arizona%%type%%</client>
    <dataSource>Local%%client%%</dataSource>
    <path>App_Data\%%type%%\%%client%%_%%dataSource%%</path>
    <targetmachines>
        <targetmachine>
        <name>Any</name>
        <remotedirectory>D:\Inetpub\Test</remotedirectory>
        </targetmachine>
    </targetmachines>
    </environment>
</configuration>
"@

[System.Xml.XmlDocument] $configxml = [xml]$xmldata
$environmentId = "Development"
$keyValuePairs = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]"
$configxml.SelectNodes("//configuration/environment[@id='$($environmentId)']//*[not(*)]") | `
    ForEach-Object {
                    if($_.ParentNode.ToString() -ne "targetmachine")
                    {

                        $keyValuePairs.Add($_.Name, $_.InnerText)
                    }
                }

"BEFORE---->"
Write-Output $keyValuePairs  | ft -AutoSize -Wrap

### loop while [Regex]::Matches($keyValuePairs.path,"%%(.+?)%%*") START

$aux = $($keyValuePairs.GetEnumerator())
for ($i=0; $i -lt $aux.Count; $i++) { 
    $auxKey = $aux[$i].Key
    $auxVal = $aux[$i].Value

    $m = [Regex]::Matches($keyValuePairs.path,"%%(.+?)%%*")
    $m | % {
        $tag = $_.Groups[1].Value
        if ( $tag -match '%%') {
            # wait until replaced
        } else {
            $keyValuePairs.$auxKey = $keyValuePairs.$auxKey -replace "%%$tag%%", $($keyValuePairs.$tag)
            $aux = $($keyValuePairs.GetEnumerator()) # renew values after replace
        }
    }
}
### loop while [Regex]::Matches($keyValuePairs.path,"%%(.+?)%%*") END

"AFTER---->"
Write-Output $keyValuePairs  | ft -AutoSize -Wrap

<强>输出

PS D:\PShell> D:\PShell\SO\42687374.ps1
BEFORE---->

Key        Value                                      
---        -----                                      
type       Dev                                        
client     Arizona%%type%%                            
dataSource Local%%client%%                            
path       App_Data\%%type%%\%%client%%_%%dataSource%%


AFTER---->

Key        Value                                  
---        -----                                  
type       Dev                                    
client     ArizonaDev                             
dataSource LocalArizonaDev                        
path       App_Data\Dev\ArizonaDev_LocalArizonaDev

答案 1 :(得分:0)

=IF(F4>0, "Should Save", IF(F4<0, "Owed", ""))